Can I just let Sapper's preload function just await a promise without it needing to return the result of that promise?

Viewed 541

I understand the thing with having a preload() function in a <script context="module"> tag, and that whatever that function returns gets passed to the component as an external property, provided you wrote export let whatever in your component.

Now I'm using firestore together with rxfire, both serverside and clientside. So I can just do an import { posts } from '../store' and then posts will literally be a store that will continuously update itself whenever it gets new snapshots from firebase's firestore.

In the Svelte tutorial I've noticed that any variable you declare in a <script context="module"> will also be available to your html template, just like when you had declared it in the normal <script> tag.

So then my train of thought was, I don't actually need the preload() function to return any properties to inject in my component. Since the posts variable is already available to the html template. The only thing I really need to do in preload() is to make sure it waits until the first data snapshot from firestore has arrived. So that would've looked something like this:

<script context="module">
  import { posts } from '../store'
  import { first } from 'rxjs/operators'

  export async function preload() {
    const result = await posts.pipe(first()).toPromise()
    console.log(result) // this is just here to check if the results did indeed arrive
  }
</script>

<h1>Recent posts</h1>

<ul>
  {#each $posts as post}
    <li>
      <a href="/blog/{post.slug}" rel="prefetch">
        {post.title}
      </a>
    </li>
  {/each}
</ul>

When I run this code I can see in my terminal that the posts data is indeed correctly printed from console.log, so I know the data arrived. But for some reason I don't understand, it doesn't work, because the template still ends up with a store that doesn't contain the first snapshot of data yet. So the SSR html that the server sends to the browser ends up with an empty list.

I thought maybe it had to do with the fact that it's a store and not a raw data-value. So I simplified my code to see if that was the problem.

<script context="module">
  import { wait } from '../utils'
  import { writable } from 'svelte/store'

  const blabla = writable('first value')

  export async function preload() {
    await wait(1000) // simulate a delay, like we would have when retrieving data from firestore
    blabla.set('second value')
  }
</script>

<h1>{$blabla}</h1>

That then the SSR html code does contain the text second value. So I don't know what the problem is.

Anyone knows what gives?

1 Answers

In the end I was able to fix it by replacing rxjs and rxfire with my own code that wraps firestore live snapshots in a svelte store. So there must just be some weird incompatibility rxjs that messed things up.

Related