So lately I’ve been trying to get my mind around some Solid 2.0 concepts. Projections especially have my interest at the moment. I don’t yet feel comfortable talking about the best ways to use them, but in playing with them a more fundamental question came to mind. Why do we use stores in the first place?
I thought I understood how stores work but apparently not to the extent I wanted to. The common wisdom is to use createSignal
for primitive values, and createStore
for more deeply nested structures. But why is that? Is there also a performance gain we get by using them?
Let’s explore!
Immutable Reactivity
createSignal
can be thought of as immutable reactivity. To update it you take the previous value and map over it returning a new value. You are replacing the entire value with a whole new value.
Let’s get an example going by creating some todos to work with:
import { createSignal, For } from "solid-js";
export default function App() {
const [todos, setTodos] = createSignal([
{ id: 1, text: "Learn SolidJS", completed: false },
{ id: 2, text: "Build app", completed: true },
]);
const toggleTodo = (id: number) =>
setTodos(todos => {
return todos.map(todo => {
if (todo.id === id) {
return { ...todo, completed: !todo.completed };
}
return todo;
});
});
// ...
}
I snuck in a little toggleTodo
function as well. In this function we look for the specific todo we want to toggle and return a new todo with its completed value flipped. We clone the entire todo every time.
Let’s return some JSX:
export default function App() {
// ...
return (
<div>
<h3>Todos:</h3>
<For each={todos()}>
{todo => (
<div>
<span
style={{
"text-decoration": todo().completed ? "line-through" : "none",
}}
>
{todo().text} {console.log("running", todo().text)}
</span>
<button onClick={() => toggleTodo(todo().id)}>
{todo().completed ? "Undo" : "Complete"}
</button>
</div>
)}
</For>
</div>
);
}
Interesting to see that we are console logging whenever todo().text
runs. This is purely for demonstrative purposes.
When you start up the dev server and run this code, what do you expect to happen? How many console logs will happen when we toggle a todo?

If you guessed one you were correct! You can also see the div
as a whole gets replaced.
Now this isn’t bad right? We don’t loop over all the todos just the one we toggled, but can we do better? This is where mutable reactivity and stores come in!
Mutable Reactivity
createStore
provides you with mutable reactivity ✨. You can do a pinpoint update by mutating the todo’s completed
property directly instead of returning a whole object.
Change our code to the below.
import { createStore, For } from "solid-js";
export default function App() {
const [todos, setTodos] = createStore([
{ id: 1, text: "Learn SolidJS", completed: false },
{ id: 2, text: "Build app", completed: true },
]);
const toggleTodo = (id: number) =>
setTodos(todos => {
const t = todos.find(t => t.id === id);
if (t) {
t.completed = !t.completed;
}
});
return (
<div>
<h3>Todos:</h3>
<For each={todos}>
{todo => (
<div>
<span
style={{
"text-decoration": todo().completed ? "line-through" : "none",
}}
>
{todo().text} {console.log("running", todo().text)}
</span>
<button onClick={() => toggleTodo(todo().id)}>
{todo().completed ? "Undo" : "Complete"}
</button>
</div>
)}
</For>
</div>
);
}
The magic in this approach is to find the todo we need, and mutate it.
const toggleTodo = (id: number) =>
setTodos(todos => {
const t = todos.find(t => t.id === id);
if (t) {
t.completed = !t.completed;
}
});
How many console.log’s show up this time?

Turns out none show up! Instead we can see it pinpoint updated only the things that depend on the completed
property and left the todo().text
alone.
Conclusion
We are slowly exploring mutable reactivity and it does take a bit of a mind shift. We are so engrained to think in an immutable way, especially if you are coming from React.
If you wish to play with the example more I have an example on stackblitz
There are also great resources from Ryan Carniato in article and video form that goes way more in depth than I ever could.
What do you think? Are you going to use stores more?