Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<Doc>: No difference between "Loading" and "Doesn't Exist" #142

Open
Kimeiga opened this issue Oct 26, 2023 · 7 comments
Open

<Doc>: No difference between "Loading" and "Doesn't Exist" #142

Kimeiga opened this issue Oct 26, 2023 · 7 comments

Comments

@Kimeiga
Copy link

Kimeiga commented Oct 26, 2023

<script>
	/**
	 * @type {string}
	 */
	export let entry;

	import { doc, setDoc } from 'firebase/firestore';
	import { SignedIn, SignedOut, Doc } from 'sveltefire';
	import { firestore } from '$lib/firebase'; // your firestore instance
	let editingNote = false;
	let newNote = '';

	function editNote(n) {
		editingNote = true;
		newNote = n;
	}

	async function saveNote(id) {
		editingNote = false;

		// set doc in firestore to newNote data
		await setDoc(doc(firestore, 'words', id), {
			note: newNote
		});
	}
</script>

{entry}

<Doc ref={`words/${entry}`} let:data>
	{#if !editingNote && data?.note === undefined}
		<SignedIn>
			<button on:click={editNote(data?.note)}>Add Note</button>
		</SignedIn>
	{:else if !editingNote}
		<p>{data?.note}</p>
		<SignedIn>
			<button on:click={editNote(data?.note)}>{data?.note ? 'Edit Note' : 'Add Note'}</button>
		</SignedIn>
	{:else if editingNote}
		<form on:submit|preventDefault={saveNote(entry)}>
			<textarea bind:value={newNote} />
			<button type="submit">Save</button>
			<button type="reset" on:click={() => (editingNote = false)}>Cancel</button>
		</form>
	{/if}

	<p slot="loading">Loading...</p>
</Doc>

I can't get this to continue beyond the loading state despite everything else working. This component is Note.svelte and it is instantiated within the context of a so everything else is available.

Without the log option, I can't see what's wrong with the Doc component.

I turned off ssr in the svelte config as well:

import adapter from '@sveltejs/adapter-auto';

/** @type {import('@sveltejs/kit').Config} */
const config = {
	ssr: false,
	kit: {
		// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
		// If your environment is not supported or you settled on a specific environment, switch out the adapter.
		// See https://kit.svelte.dev/docs/adapters for more information about adapters.
		adapter: adapter()
	}
};

export default config;

What is going wrong?

Nothing in console as well btw

@Kimeiga
Copy link
Author

Kimeiga commented Oct 26, 2023

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {

    // This rule allows anyone with your Firestore database reference to view, edit,
    // and delete all data in your Firestore database. It is useful for getting
    // started, but it is configured to expire after 30 days because it
    // leaves your app open to attackers. At that time, all client
    // requests to your Firestore database will be denied.
    //
    // Make sure to write security rules for your app before that time, or else
    // all client requests to your Firestore database will be denied until you Update
    // your rules
    match /{document=**} {
      allow read: if true;
      allow write: if request.auth.uid != null;
    }
  }
}

the firestore rules allow authenticated writes and I definitely can read. I am signed in on my app as well

@Kimeiga
Copy link
Author

Kimeiga commented Oct 26, 2023

Ok so specifically, there's no way to tell if a Document is just not there, or if it's still loading since the loading slot is triggered in both cases.

I'm making a dictionary app where you can take notes on words, and those words are in a collection called "words" and they are located at words/{word}

I would like to have the ability to do

<Doc ref={`words/${word}`} let:data>
  {data.note}
  <div slot="no-data">
    <button>Add data</button>
  </div>
  <div slot="loading">
    Loading
  </div>
</div>

@Kimeiga
Copy link
Author

Kimeiga commented Oct 26, 2023

{#if data == undefined}
hi
{/if}

I tried every permutation of these but I don't think anything like this will work because only the loading state is shown if there's no data

<script lang="ts" generics="Data extends DocumentData">
  import type {
    DocumentData,
    DocumentReference,
    Firestore,
  } from "firebase/firestore";
  import { docStore } from "../stores/firestore.js";
  import { getFirebaseContext } from "../stores/sdk.js";

  export let ref: string | DocumentReference<Data>;
  export let startWith: Data | undefined = undefined;

  const { firestore } = getFirebaseContext();

  let store = docStore(firestore!, ref, startWith);

  interface $$Slots {
    default: {
      data: Data;
      ref: DocumentReference<Data> | null;
      firestore?: Firestore;
    };
    loading: {};
  }
</script>

{#if $store !== undefined && $store !== null}
  <slot data={$store} ref={store.ref} {firestore} />
{:else}
  <slot name="loading" />
{/if}

@Kimeiga
Copy link
Author

Kimeiga commented Oct 26, 2023

I tried a few other things

<script>
const post = docStore(firestore, `words/${entry}`);
console.log(post);
console.log($post);

let docSnap;
onMount(async () => {
docSnap = await getDoc(doc(firestore, `words/${entry}`));
});
</script>
....


<div slot="loading">
{#if docSnap && docSnap.exists()}
	exists
{:else}
	doesn't exist
{/if}

{#if $post == undefined}
	hi
{:else}
	loading...
{/if}
</div>

exists() returns after a second true or false so maybe we could have have the following behavior

Loading
exists() comes back false -> Doesn't-Exist
exists() comes back true -> Shows Content

@Kimeiga
Copy link
Author

Kimeiga commented Oct 26, 2023

<script>
	/**
	 * @type {string}
	 */
	export let entry;

	import { doc, getDoc, setDoc } from 'firebase/firestore';
	import { SignedIn, SignedOut, Doc, docStore } from 'sveltefire';
	import { firestore } from '$lib/firebase'; // your firestore instance
	import { onMount } from 'svelte';
	let editingNote = false;
	let newNote = '';

	function editNote(n) {
		editingNote = true;
		newNote = n;
	}

	async function saveNote(id) {
		editingNote = false;

		// set doc in firestore to newNote data
		await setDoc(doc(firestore, 'words', id), {
			note: newNote
		});
	}
	const post = docStore(firestore, `words/${entry}`);
	console.log(post);
	console.log($post);

	let docSnap;
	onMount(async () => {
		docSnap = await getDoc(doc(firestore, `words/${entry}`));
	});

	let exists = true;
	$: exists = docSnap && docSnap.exists();
</script>

<Doc ref={`words/${entry}`} let:data let:ref>
	{#if !editingNote}
		<p>{data?.note}</p>
		<SignedIn>
			<button on:click={editNote(data?.note)}>{data?.note ? 'Edit Note' : 'Add Note'}</button>
		</SignedIn>
	{:else if editingNote}
		<form on:submit|preventDefault={saveNote(entry)}>
			<textarea bind:value={newNote} />
			<button type="submit">Save</button>
			<button type="reset" on:click={() => (editingNote = false)}>Cancel</button>
		</form>
	{/if}

	<div slot="loading">
		{#if exists}
			<span>Loading</span>
		{:else}
			<SignedIn>
				<form on:submit|preventDefault={saveNote(entry)}>
					<textarea bind:value={newNote} />
					<button type="submit">Add Note</button>
					<button type="reset" on:click={() => (editingNote = false)}>Cancel</button>
				</form>
			</SignedIn>
		{/if}
	</div>
</Doc>

I ended up having to do this; sort of buggy and annoying though

@Kimeiga Kimeiga changed the title Docs always stuck at loading <Doc>: No difference between "Loading" and "Doesn't Exist" Oct 26, 2023
@anasmohammed361
Copy link

#96

@anasmohammed361
Copy link

i'll drop a pr for this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants