Innovations of SolidJS 2

unlog1 pts0 comments

Innovations of Solid 2.0

Go back<br>Innovations of Solid 2.0<br>Posted on:August 13, 2026<br>Introduction

So Solid 2.0 release candidate is now out and I’ve been trying to think of how to best market it. It’s not just a “faster React”, it’s something different. Something pushing the boundaries of what’s possible with frontend UIs.

Today I want to show you why it’s worth paying attention to by showcasing its innovations.

Async is derived and part of the graph

Async is the main headlining feature of Solid 2.0. It is the source of a lot of app complexity and in 2.0 Solid takes this head on for you. Work on Solid 2.0 began a long time ago, and Ryan has been thinking about this problem even longer.

The first inkling of modeling async as derived was the gaining popularity of Tanstack Query. This eventually led to the async solutions we have now. Async used to be seen as something outside of the system. E.g. fetching in a useEffect.

In Solid 2.0, async is just part of the reactive graph. You can hand a promise to a derived value and read it like anything else:

const user = createMemo(() => fetchUser(props.id));

// read it like a normal signal; the boundary handles the rest<br>return h1>{user().name}h1>;<br>So why should you care?

Performance - blocking higher than needed with async is the biggest cause of slow loading times. When async lives in the graph, the framework can see your data flow — which opens the door to things like detecting waterfalls for you.

DX - Figuring out how to structure your async is the source of a lot of bugs in applications these days. if(loading) guards can be a thing of the past.

Coordinated async as the default

This builds off the previous concept. With async being a part of the graph it makes sense that we can coordinate it. Have you ever pressed a button multiple times just to have the UI flicker through intermediate states that are useless? This is what uncoordinated async looks like. The network requests all come in at separate times and make for a janky experience.

Solid takes inspiration from both React and Svelte here. Svelte asked why can’t we coordinate all async without an explicit transition api. Solid took this and applied React’s stronger guarantees on top of it.

With this coordination in place Solid can also hold values in the past, and prevent the yank back to Suspense fallback.

Now making all async coordinated usually makes for poor performance — you’re potentially keeping two versions of the world alive at once. Solid innovated here with their disposal system to not take a big hit.

So why should you care this time?

UX - Adds the ability to make less janky UIs.

DX - It’s just easier to implement UIs in a correct way.

Stores are a superpower

Stores are unique to Solid. Svelte has collapsed them into one $state rune, and React just has useState. This split is intentional in Solid and it’s not something I understood for a very long time. They are a way to represent objects or arrays as a collection of signals. You update one leaf of the state, and the rest of the state stays quiet.

const [todos, setTodos] = createStore([...]);

// only the checkbox for todo 3 updates — nothing else re-runs<br>setTodos(todos => {<br>todos[3].done = true<br>});<br>They are also seen as mutable reactivity, the counterpart to immutable reactivity found in most other frameworks. This is why the Solid store setter uses a produce style draft that you mutate. This allows you to keep identity of rows, even when you refresh from the server and reconcile the data — your list doesn’t get torn down and rebuilt just because the server sent fresh JSON.

Benefits this time are mostly performance based, and they compound with everything else in this post. Stores are what make the optimistic state story below so clean.

Optimistic state that makes sense

Optimistic state is something I’ve generally found pretty cumbersome. For this reason, I haven’t actually used useOptimistic in React too much. Solid’s optimistic state just makes sense.

Optimistic state is treated as a temporary overlay on top of the source of truth. It lasts only for the lifetime of a transition. Not having to worry about doing the revert yourself is great.

When things hold by default like they do in Solid, you usually either want to show a loading indicator or pretend the future is already here. With Solid you can do both with isPending and createOptimistic.

Combine optimistic state with stores and the whole pattern collapses down to almost nothing:

const [optimisticTodos, setOptimistic] = createOptimisticStore(todos);

const addTodo = action(async newTodo => {<br>setOptimistic(todos => todos.push(newTodo)); // instant UI<br>await saveTodo(newTodo); // server catches up<br>refresh(todos);<br>});<br>Optimistic state is pretty crucial for some applications so definitely a UX win. Just look at the popular Trello demos that were being built a while ago. Making the UX win as easy to accomplish as possible is surely also a DX win. The Trello demos have...

solid async state todos optimistic react

Related Articles