Remembering State in Client
Learning objectives
- You know how to store state in the client.
In the state functionality that we've used so far, the state is remembered only for the duration of the page being open. At the latest, when you refresh the page, the state is reset to its initial value. This is because the state is stored in the memory of the browser. When you refresh the page, the browser reloads the page, and the memory is reset.
If you want to remember the state even after the page is refreshed, you need to store the state. Browsers come with functionality for this. The localStorage is a global object that is available in browsers. It has methods for storing data (setItem), for retrieving data (getItem), for deleting data (removeItem), and for checking whether a key exists (hasOwnProperty).
To use local storage for storing the state, we need to adjust the functionality used for storing the state. First, we'd have to check whether the local storage has the state stored. If it does, we'd have to use the stored state. If it doesn't, we'd have to use the initial state.
As an example, for our component that stores the count, the functionality would look as follows (assuming that we'd use the key "count" for storing the state to localstorage):
let initialCount = 0;
if (
typeof window !== "undefined" &&
localStorage.hasOwnProperty("count")
) {
initialCount = parseInt(localStorage.getItem("count"));
}
let count = $state(initialCount);
The typeof window !== "undefined"
part of the code is used because the local storage is not available any in server-side rendering (which Svelte does to some extent, but which we mostly skip here). The localStorage.hasOwnProperty("count")
part of the code checks whether the local storage has the key "count". If it does, we use the value of the key as the initial value for the state, parsing the value into an integer. If it doesn't, we use the initial value of 0.
Then, we need to adjust the functionality for updating the state. Here, we'd modify the increment
function to store the value of count
to the localstorage, in addition to incrementing the count. The below highlights the full functionality for using localstorage for storing the count.
let initialCount = 0;
if (
typeof window !== "undefined" &&
localStorage.hasOwnProperty("count")
) {
initialCount = parseInt(localStorage.getItem("count"));
}
let count = $state(initialCount);
const useCountStore = () => {
return {
get count() {
return count;
},
increment: () => {
count++;
localStorage.setItem("count", count);
},
};
};
export { useCountStore };
With the above code, the count is stored to the localstorage every time the count is incremented, and loaded from localstorage whenever the page is opened.
When you use the above code, you might notice that the count is very briefly 0 even though count is not updated when you increment it. We'll ignore it.
String-formatted data in localStorage
The data is stored as strings in the localstorage. This means that if you want to store more complex data, such as a JavaScript object, you need to convert it to a string before storing it. You can use the JSON.stringify function for this. When you retrieve the data, you need to convert it back to the original data type. You can use the JSON.parse function for this.