Understanding State Management in Svelte Applications

State management is an important part of every modern web application. Each major web development framework, like React and Vue, has different ways of handling state.
Svelte is no exception, and the library offers several approaches to tackling the problem of state and how to manage it.
What Is State Management and Why Is It Important?
In web development, “state” refers to the data that informs the current situation of a page or part of it. Think of creating a shopping website with lots of pages. People can look at things to buy, put items in a cart, and then pay.
If you want the cart icon to show the number of items it contains, no matter what the current page is, you’d find state management really useful. It will ensure the cart updates immediately whenever the user adds or removes items, no matter where they are on the site.
State management is important because it makes it easier to keep track of the data flow across an app’s components. On the user’s end, proper state management should result in a more efficient, less frustrating experience.
State Management in Svelte
At the most basic level, you can define and update a state variable in Svelte using the equals sign (=). For example, if you want the text-content of a h1 to reflect a particular state variable, you can do the following:
<script>
let count = 0;
</script><h1>
{count}
</h1>
<button on:click={()=>count=count + 1}> Increase Count </button>
This code block defines a state variable, count, with the default value of “0”. It also sets the content of the h1 element to the current value of this count variable. Finally, it gives the user a way of increasing the count state variable by clicking the button.
Updating an Array State Variable in Svelte
Take a look at the following code block:
<script>
let todoList = [
"Read my books",
"Eat some foods",
"Bath the dogs",
"Take out the garbage",
]; function removeLastItem() {
todoList.pop();
}
</script>
<ul>
{#each todoList as item}
<li>{item}</li>
{/each}
</ul>
<button on:click={() => removeLastItem()}> Remove last item</button>
This code block binds an array to the state variable, todoList. When you click the Remove last item button, it runs the removeLastItem() function which removes the last item of the todoList variable.
However, if you run this code in a browser, you will notice that, when you click the button to remove the last item, the list does not update.
Svelte reacts to assignment with the equals sign, so it won’t trigger any updates after a call to Array.pop(). To get around this, you can trick Svelte into re-rendering the list by assigning the todoList variable to itself:
function removeLastItem() {
todoList.pop();
todoList = todoList;
}
When you run the code in the browser, the state array should update properly when you click the button.
Managing State With Svelte Stores
Stores make it easy to share state between unrelated components. A store in Svelte is simply an object that you can hook into and listen for changes with the subscribe method. To write a simple read-and-write store, begin by importing the writable function from the svelte/store JavaScript module, like this:
import { writeable } from "svelte/store"
Let’s say, you have a store.js file that contains the following:
import { writable } from "svelte/store";export const todoList = writable([
"Read my books",
"Eat some foods",
"Bath the dogs",
"Take out the garbage",
"Water the flowers"
]);
This code establishes a constant, todoList, and feeds an array into the writable function. You can now import the store variable into any component you want to use it with:
<script>
import { todoList } from "./store";
</script>
If you want to reference the variable, you use the subscribe method like this:
let list;todoList.subscribe((items)=>{
list = items;
})
The callback function of the subscribe method takes in the existing store value as its argument and sets the list local variable to the items argument. Now, you can render every element in the list array like this:
<ul>
{#each list as item}
<li>{item}</li>
{/each}
</ul>
To update the store value, use the update() method. The callback function of this method takes in the current store value and returns the new element to be set to the store.
todoList.update((items) => {
items.pop();
return items;
});
Creating Read-Only Stores in Svelte
Sometimes, you might want to restrict a component’s access to a store by making it read-only. To do so, use the readable function.
import { readable } from 'svelte/store';export const todoList = readable([
"Read my books",
"Eat some foods",
"Bath the dogs",
"Take out the garbage",
"Water the flowers"
]);
The update() method is not available on readable store values, so something like the following will throw an error:
function removeLastItem() {
todoList.update((items) => {
items.pop();
return items;
});
}
Using Stores With the Context API
Svelte has a Context API that you can use by importing the setContext function from the svelte module:
import {setContext} from "svelte"
To pass data from a parent component down to a child component you can do the following:
<script>
let age = 42;
</script><ChildComponent age={age} />
This approach works well, but the Context API provides a way for components to communicate with each other without passing around data. React provides similar functionality with the useContext hook. Since Context in Svelte is not reactive, you need to pass a store value to the context to make it reactive.
In the parent component, you could have the following:
<script>
import { writable } from "svelte/store";
import Component2 from "./Component2.svelte";
import { setContext } from "svelte"; let numberInStore = writable(42);
setContext("age", numberInStore);
</script>
<ChildComponent />
<button on:click={() => $numberInStore++}>Increment Number</button>
The code block above defines a store and passes the store to the setContext function alongside a key “age”. In Svelte, you can reference a store value by prepending a “$” before the store name.
Any child component can now use the context value from a parent component, by calling the getContext function and passing in the appropriate key.
<script>
import { getContext } from "svelte";
let userAge = getContext("age");
</script><h1>
{$userAge}
</h1>
State Management in Svelte vs. React
State Management in Svelte is much simpler than React—You only need an equals (=) sign to define and update state. In web frameworks like React, you’d need hooks like useState and useReducer to handle simpler state management tasks.
For sharing complex states between components, you can use the React Context API or external libraries like Redux and Zustand. In Svelte, there is virtually no need for an external library when handling complex states, because Svelte Stores and the Svelte Context API are there to do the job for you.