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

Add ability to react to a document not existing. #162

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/src/pages/firestore/doc-component.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ The `Doc` component is a wrapper around the `docStore`. It renders the document

- `default` - The document data
- `loading` - Loading state
- `notExist` - A document does not exist for the provided ref

### Slot Props

Expand All @@ -36,5 +37,6 @@ The `Doc` component is a wrapper around the `docStore`. It renders the document
<p>{data?.title}</p>

<p slot="loading">Loading...</p>
<p slot="notExist">Post does not exist</p>
</Doc>
```
25 changes: 24 additions & 1 deletion docs/src/pages/firestore/doc-store.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,27 @@ With TypeScript:
</script>

{$post?.title}
```
```

Check if post does not exist:

```svelte
<script lang="ts">

interface Post {
title?: string;
content?: string;
}

const post = docStore<Post>(firestore, 'posts/id');
const postState = post.stateStore;
</script>

{#if !$postState.loading && !$postState.exists}
Post does not exist
{:else}
{$post?.title}
{/if}
```


10 changes: 7 additions & 3 deletions src/lib/components/Doc.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
const { firestore } = getFirebaseContext();

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

interface $$Slots {
default: {
Expand All @@ -21,11 +22,14 @@
firestore?: Firestore;
};
loading: {};
notExist: {};
}
</script>

{#if $store !== undefined && $store !== null}
<slot data={$store} ref={store.ref} {firestore} />
{:else}
{#if $state.loading}
<slot name="loading" />
{:else if !$state.exists}
<slot name="notExist" />
{:else if $store !== undefined && $store !== null}
<slot data={$store} ref={store.ref} {firestore} />
{/if}
43 changes: 35 additions & 8 deletions src/lib/stores/firestore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,16 @@ import type {
Firestore,
} from "firebase/firestore";

interface DocState {
loading: boolean;
exists: boolean | null;
}

interface DocStore<T> {
subscribe: (cb: (value: T | null) => void) => void | (() => void);
stateStore: {
subscribe: (cb: (value: DocState) => void) => void | (() => void);
};
ref: DocumentReference<T> | null;
id: string;
}
Expand All @@ -26,36 +34,52 @@ export function docStore<T = any>(
): DocStore<T> {
let unsubscribe: () => void;

// Fallback for SSR
if (!globalThis.window) {
function noopStore() {
const { subscribe } = writable(startWith);
const { subscribe: existsSubscribe } = writable({
loading: true,
exists: null,
});

return {
subscribe,
stateStore: {
subscribe: existsSubscribe,
},
ref: null,
id: "",
};
}

// Fallback for SSR
if (!globalThis.window) {
return noopStore();
}

// Fallback for missing SDK
if (!firestore) {
console.warn(
"Firestore is not initialized. Are you missing FirebaseApp as a parent component?"
);
const { subscribe } = writable(null);
return {
subscribe,
ref: null,
id: "",
};
return noopStore();
}

const docRef =
typeof ref === "string"
? (doc(firestore, ref) as DocumentReference<T>)
: ref;

const state = writable<DocState>({
loading: true,
exists: null,
});

const { subscribe } = writable<T | null>(startWith, (set) => {
unsubscribe = onSnapshot(docRef, (snapshot) => {
state.set({
loading: false,
exists: snapshot.exists(),
});
set((snapshot.data() as T) ?? null);
});

Expand All @@ -64,6 +88,9 @@ export function docStore<T = any>(

return {
subscribe,
stateStore: {
subscribe: state.subscribe,
},
ref: docRef,
id: docRef.id,
};
Expand Down