SolidJS - Looks Can Be Deceptive?
Solid JS is a relative newcomer to the JavaScript framework scene. And yet it ranks first in popularity in this year's State of JavaScript survey. What makes it so attractive, and is it worth learning?
It's like React… at first glance
When you read SolidJS code, it looks a lot like React. A component is a function that returns JSX code. If you are at all familiar with React you can read SolidJS code and get a good idea of what is going on. In fact, the following code is valid in both React and Solid:
function MyComponent(props) {
return <div>Hello {props.name}</div>;
}
<MyComponent name="Solid" />;
`And that is a good thing. There are already enough different frameworks each pushing its own syntax. And React is the *de facto *standard. So it is nice to be in familiar territory.
Except that it is not. Because hooks — which are the backbone of React's business logic — don't even exist in Solid JS.
Using Signals instead of useState
Solid does not have a useState hook. Instead, it relies on "signals". What is a signal? In Solid, signals are initialised like this:
const [count, setCount] = createSignal(0);
Given the familiar syntax, it's easy to imagine that createSignal is just a variation on React's "useState". And in a sense, both serve to solve the same problem: tracking the application state across executions of the component functions. So what is the difference between SolidJS's signals and React's useState hooks?
The first hint of a clue is that the first element returned by createSignal
(so "count", in the example above) is a function. Solid JS's website states: "Signals are event emitters that hold a list of subscriptions". What does that mean in practice?
The documentation also states that component functions "are called once and then cease to exist". They "exist to organise your code and not much else". So despite the similarities in how the code is written, it feels like the underlying mechanisms are very different.
React tracks state changes across the component tree using a Virtual DOM. And then React re-renders the tree based on where the changes occur in the tree. The Tree is compared. And component functions are called repeatedly. The whole component, and its children, are re-rendered whenever any part of its state changes.
Solid, on the other hand, tracks which part of the UI depends on what. And it updates that and nothing else.
And that feels very familiar
Solid manages state like Svelte
Svelteclaims to be the vanishing framework. Instead of comparing state changes across a virtual DOM (as React and others do), it overloads the JavaScript syntax to track dependencies. In that sense, it is first and foremost a compiler. And because it knows which part of the interface depends on which variable, it is surgically precise in its updates.
And what Solid JS is doing feels very similar to this: the parts of the interface that change are plugged into event listeners. The side effects (the useEffect equivalents) plug themselves into these event listeners.
So why not just use Svelte or React, instead of turning to some (relatively) new upstart?
Making solid sense
To me (and this may well just be a matter of taste), Svelte feels too much like magic. It looks like JavaScript, but the compiler is layering on dependency dark arts on top of that.
Solid, on the other hand, makes more sense than Svelte. It's just cleverly organized event listeners, not some compiler magic. Event listeners, I know, understand, and trust. Compilers doing strange stuff to my code… not so much so.
When you think about it, Solid even makes more sense than React. The mistakes I've seen junior developers make shows they haven't grasped when functional components are called or how the state is managed.
And in a sense that is the hardest thing about Solid JS.
Concepts that I've learned about React, that have become ingrained in the way I code, about how to manage state and the render, don't transpose well to Solid JS. I don't need to worry about how often components are called — because they are only called once.
In both these cases, in how Solid implements reactivity and manages HTML rendering, Solid feels saner than its "parents", Svelte and React.
Better than the sum of its parts?
All this combines to produce code that is effective and fast. Solid JS scores very highly on the JavaScript framework benchmark. It's very highly regarded in the State of JavaScript survey. And it weighs in at only 7kb.
So why will I not be using Solid JS just yet?
Well, part of the problem is that Solid JS is not React, and a lot of the projects I'm involved in already have a big React codebase. The people working on them know React, and they don't know Solid.
But I have the feeling that here and there, where React was causing performance problems, on projects where I can work alone, I'll be sprinkling in a bit of Solid JS here and there.
And who knows, maybe someday I'll be using it exclusively. Because I love Svelte's reactivity, but I'm not a fan of its compiler magic. And I love React's JSX syntax and simplicity, but I've seen too many people tripped up by behaviour they don't understand.
And Solid JS looks like it might be bringing together the best of both worlds, in a way that is both simple, sane and … solid.
We help you better understand software development. Receive the latest blog posts, videos, insights and news from the frontlines of web development