visit
State management is usually one of the most important problems that you need to tackle when developing a frontend application. This article discusses state management for SolidJS, which is a library for building web applications that are small and extremely fast. If you are new to Solid but already familiar with React you may want to read an introduction to SolidJS first.
Let's start with the most fundamental building blocks of Solid's reactivity system: signals.import { render } from "solid-js/web";
import { createSignal } from "solid-js";
function Counter() {
const [count, setCount] = createSignal(0);
return (
<div>
<button onClick={() => setCount((c) => c - 1)}> - </button>
{count()}
<button onClick={() => setCount((c) => c + 1)}> + </button>
</div>
);
}
render(() => <Counter />, document.getElementById("app"));
const [state, setState] = createStore({
todos: [
{ task: 'Finish work', completed: false }
{ task: 'Go grocery shopping', completed: false }
{ task: 'Make dinner', completed: false }
]
});
setState('todos', [0, 2], 'completed', true);
// {
// todos: [
// { task: 'Finish work', completed: true }
// { task: 'Go grocery shopping', completed: false }
// { task: 'Make dinner', completed: true }
// ]
// }
setState('todos', { from: 0, to: 1 }, 'completed', c => !c);
// {
// todos: [
// { task: 'Finish work', completed: false }
// { task: 'Go grocery shopping', completed: true }
// { task: 'Make dinner', completed: true }
// ]
// }
setState('todos', todo => todo.completed, 'task', t => t + '!')
// {
// todos: [
// { task: 'Finish work', completed: false }
// { task: 'Go grocery shopping!', completed: true }
// { task: 'Make dinner!', completed: true }
// ]
// }
setState('todos', {}, todo => ({ marked: true, completed: !todo.completed }))
// {
// todos: [
// { task: 'Finish work', completed: true, marked: true }
// { task: 'Go grocery shopping!', completed: false, marked: true }
// { task: 'Make dinner!', completed: false, marked: true }
// ]
// }
While I can see that the syntax is powerful, it doesn't seem very intuitive. Luckily, Solid also provides a couple of alternatives for updating stores. The first alternative is using a mutable store by calling
createMutable()
instead of createStore()
. This way, you can update the store like you would do with a normal JavaScript object:const store = createMutable({ firstName: "John", lastName: "Doe" });
// read value
store.firstName
// set value
store.firstName = anotherValue
While using a mutable store is very simple, it could be hard to reason about when changes are made from many places in the application. Thus I would recommend the second alternative, which is to use an Immer inspired utility function called
produce()
. This utility allows us to write code that mutates data in the normal way but automatically creates immutable copies behind the scenes.const store = createStore({ firstName: "John", lastName: "Doe" });
// read value
store.firstName
store.lastName
// set value
setState(produce(s => {
s.firstName = anotherFirstName
s.lastName = anotherLastName
}))
This article has introduced the two built-in options for state management in a Solid application. Use signals for atomic pieces of data. Use a store if the state is a complex structure whose parts can be modified independently. Use the path syntax or the
produce()
utility for updating stores. You don't need a state library like Redux or MobX. For most applications, using one or more stores to manage the application state should be sufficient.