问题
In a Sapper app, I want to be able to persist the state of some UI components so I can navigate the app without losing state when the user returns to the pages using those components.
In a Svelte-only app, this is usually done with a custom store that uses the sessionStorage
or localStorage
API. A good example of that can be found in R. Mark Volkmann's book Svelte and Sapper in Action, §6.24:
store-util.js
import {writable} from 'svelte/store';
function persist(key, value) {
sessionStorage.setItem(key, JSON.stringify(value));
}
export function writableSession(key, initialValue) {
const sessionValue = JSON.parse(sessionStorage.getItem(key));
if (!sessionValue) persist(key, initialValue);
const store = writable(sessionValue || initialValue);
store.subscribe(value => persist(key, value));
return store;
}
Unfortunately, using stores that way breaks immediately in Sapper because the scripts run on the server first, where sessionStorage
is not defined. There are ways to prevent some parts of code from running on the server (using the onMount
lifecycle function in a component, or checking process.browser === true
), but that doesn't seem possible here.
Persisting some state locally looks like a very common use case so I'm wondering what's the right way to do it in a Sapper app (considering that I haven't even found the wrong way).
回答1:
Provide a dummy store for SSR.
It is always possible to do feature detection with something like typeof localStorage !== 'undefined'
.
Your component code will re-run in the browser, even if the page was SSR'd. This means that if it is fed a different store, the browser-only values will take over and update existing state (inherited from the server).
See this answer for an example.
来源:https://stackoverflow.com/questions/65740245/how-to-persist-ui-component-state-data-in-sapper