nanostores/query

Add examples for initializing fetchers and mutators with initial data

Todomir opened this issue · 4 comments

It is a very common pattern to load initial data on the server, pass it to the cache and then have the client take over from there, but I don’t see any example or options for this pattern anywhere. Is it currently possible? If not, is it on the roadmap?

Examples:

dkzlv commented

We explore a more robust way to implement SSR throughout the whole entirety of nanostores. You can track it in this issue in the core repo.

An honest answer would be that currently we don't really support SSR it in any meaningful way. If you really want to explore this before we finish the work in the upstream libs, you can try to go that way:

  1. provide any nanoquery context a custom cache backend (basically, a new Map())
  2. start rendering the app
  3. wait till allTasks() resolves
  4. serialize the cache, put it into DOM
  5. write a function that will get the cache from the DOM if it's present during module initialization; if not—fall back to new Map() once again.

Nanoquery won't refetch stuff that was fetched on the backend.

I have a similar case, but my React application is not rendered on the server.
But the server provides some initial data in JSON format right in HTML.

Do I understand correctly that it will be enough to do something like this?

const serializedState = document.querySelector('script[data-state-from-server]')
const deserializedState = JSON.parse(serializedState.textContent)
const cacheKeys = ['key1', 'key2', 'key3']
const initialCache = new Map()

initialCache.set(cacheKeys, deserializedState)

const cache = nanoquery({
  cache: initialCache,
  ...
})
dkzlv commented

@tatarianBarbarian Yeaaah, no, I'm afraid that won't work.

Here's an SB project with a demo. I wrote it for issue #15, but the takeaways are the same, since it doesn't really matter what's the source of "reviving" the cache: it can be SSR, it can be LS, it doesn't matter.

So your idea will work in a sense that it will show the correct initial state, but unfortunately it will refetch everything on mount. The reason is rather simple: everything related to deduplication and cache TTL is stored outside of nanostores right now, and it cannot be received or set from the outside. If it's crucial for your project to avoid refetches, I can come up with some design to allow setting meta (most notably, _lastFetch map) from the outside.

@tatarianBarbarian Yeaaah, no, I'm afraid that won't work.

Here's an SB project with a demo. I wrote it for issue #15, but the takeaways are the same, since it doesn't really matter what's the source of "reviving" the cache: it can be SSR, it can be LS, it doesn't matter.

So your idea will work in a sense that it will show the correct initial state, but unfortunately it will refetch everything on mount. The reason is rather simple: everything related to deduplication and cache TTL is stored outside of nanostores right now, and it cannot be received or set from the outside. If it's crucial for your project to avoid refetches, I can come up with some design to allow setting meta (most notably, _lastFetch map) from the outside.

Sounds valid to me. Feels like there is no need to fetch data that is already there.
It can also save some server time on larger projects.
(but we'll need some docs on how to use it 😅)