Common Patterns
Fetch Data from Firestore for Authenticated Users
First, Use the SignedIn
component to access the UID of the current user. Second, pass that UID to the Doc
or Collection
component to fetch a Firestore document owned by that user.
<SignedIn let:user>
<Doc ref={`posts/${user.uid}`} let:data={post}>
<h2>{post.title}</h2>
<p>{post.content}</p>
</Doc>
</SignedIn>
SSR with SvelteKit
SvelteFire is a client-side library, but allows you to hydrate server data into a realtime stream.
First, fetch data from a load function like so:
// +page.ts
import { doc, getDoc } from 'firebase/firestore';
export const load = (async () => {
const ref = doc(firestore, 'posts', 'first-post');
const snapshot = await getDoc(ref);
return {
post: snapshot.data();
};
});
Second, pass the server data as the startWith
value to a store. This will bypass the loading state and ensure the data is rendered in the server HTML, then realtime listeners will be attached afterwards.
// +page.svelte
<script lang="ts">
export let data: PageData;
</script>
<!-- Example using component -->
<Doc startWith={data.post} ref="posts/first-post" let:data={post}>
<h2>{post.title}</h2>
<p>{post.content}</p>
</Doc>
Note: This will result in 2 reads from Firestore on initial page load, so only use this pattern when true realtime data necessary.
Dynamic Firestore Queries
Imagine you have a collection of posts what a user can filter by category. Create a reactive declaration to re-run the query whenever the category changes.
<script lang="ts">
import { query, collection, where } from 'firebase/firestore';
let category = 'tech';
$: q = query(
collection(firestore, `posts`),
where('category', '==', category)
);
</script>
<Collection ref={q} let:data={posts}>
<ul>
{#each posts as post (post.id)}
<li>{post.content}</li>
{/each}
</ul>
</Collection>
<button on:click={() => category = 'sports'}>Sports</button>
Handle File Uploads with Progress Bar
The example below shows how to upload a file to Firebase Storage and display a progress bar. First, get a file from the user. Second, pass the file to the UploadTask
component. Third, display the progress bar and download link.
<script lang="ts">
let file: File;
let filePath = "things/test.png";
function chooseFile(event) {
file = event.target.files[0];
}
</script>
<input type="file" on:change={chooseFile} />
{#if file}
<UploadTask ref={filePath} data={file} let:progress let:snapshot>
{#if snapshot?.state === "running" || snapshot?.state === "success"}
<p>{progress}% uploaded</p>
<progress value={progress} max="100" />
{/if}
{#if snapshot?.state === "error"}
Upload failed
{/if}
{#if snapshot?.state === "success"}
<DownloadURL ref={snapshot?.ref} let:link let:ref>
<a href={link} download> {ref?.name} </a>
</DownloadURL>
{/if}
</UploadTask>
{/if}