Introduction to SolidJS
Hey there. You probably heard a lot of things about SolidJS in recent months, and if you are still on the fence, this is the video for you. If you are new to this channel, welcome. For a bit of context, I'm a developer with more than 10 years of front-end experience. During this time I got a chance to work with a wide variety of libraries and Frameworks, but I mostly consider myself a React guy.
These days, the front-end space is in constant change, and some of the new tools the community is releasing these days are pretty mind-blowing. SolidJS is part of the new wave of UI libraries that are changing the way we think about web apps, and I see it as a real alternative to established Frameworks such as React moving forward. Without further ado, let's jump right into it.
Reason 1: Simplicity and Familiar JSX
First and foremost, I love how simple everything is in Solid. Let's take a look at the basic Solid component, and I'll show you how smart the team behind Solid was about all these. For better or worse, we are close to the 15-year mark in modern front-end development, and some patterns or techniques emerge as best practices regardless of your framework reference.
As an FYI, I might be subjective, but I consider October 2010 when AngularJS and Backbone were first released the beginning of the modern front-end development era. Back to the code. Templating using JSX is one of those things that gained traction for all the right reasons. While the mix of JavaScript and HTML might look a bit weird in the beginning, JSX turned out to be flexible and powerful, especially since there aren't any special templating concepts, elements, or directives you need to know. At the end of the day, JSX is still plain JavaScript, so you can simply use if to conditionally render elements or array maps to iterate through lists. Also, note that Solid components are plain JavaScript functions returning JSX. This is a concept popularized by React, and I appreciate Solid is not reinventing the wheel here. If something works well and the community is on board with it, there is no reason to change it.
Reason 2: No Virtual DOM
Okay, so until now, we've seen that just like React, Solid apps are built using function components and JSX. What are the differences then? Well, I'll mention the lack of the virtual DOM first. This might sound unusual, especially since all the big frameworks like Angular or React are using this abstraction, but again, Solid is focused on simplicity. The need for a virtual DOM arises from the poor performance of the real DOM. In recent years, however, browsers drastically improved their strategies of working with the DOM. The resulting performance gains are more than enough to allow libraries to directly alter the real DOM. So the virtual DOM obstruction became a redundant additional layer with very few use cases. By dropping the virtual DOM, Solid is smaller and has a codebase more targeted on the actual needs of web apps.
Reason 3: Fine-Grained Reactivity
The second thing Solid excels at is reactivity. Signals are the building blocks here, and it is extremely straightforward to work with them. You can define signals by using the createSignal hook, and you can build new constructs that depend on signals by wrapping them in functions. The resulting expressions are called derived signals. On top of signals, Solid offers an observer implementation called effects. These can keep track of signal values by subscribing to them during the function execution. Anytime the signal is changed, the effect function will be run. While the signal plus effect combination gives you a straightforward solution for reactivity, not everybody got it right.
I discussed previously about the newer libraries building on top of knowledge gained by older tools while also getting the chance to address some of the existing pitfalls. You can find more details on this topic in the video linked in the top right corner. I'll not get into many details here, but I want to mention the example of Solid's reactivity compared to React's rendering and reconciliation process. While in Solid, only effects and derived signals rerun when signals are changed, in React, the entire component function re-runs every time state or properties are updated. This leads to a lot of overhead, side effects, and constraints you have to keep in mind while building your app.
Solid reactivity is synchronous. In other words, code is evaluated line by line, and the DOM is updated immediately according to the changes. In our example, in the on-click callback, two triggers are updated as follows: first, the setMemberName line is evaluated, as a result, the DOM name element is updated. Then setLastClick line is evaluated, as a result, the DOM time element is updated. This is fine for most cases, but Solid allows you to batch updates together, and this is useful if the values are related.
Before moving to the third Solid feature I really like, I want to briefly mention memos. Most of the time, composing derived signals is sufficient. However, it is sometimes beneficial to cache values in order to reduce duplicated work. We can use memos to evaluate a function and store the result until its dependencies change.
Reason 4: Control Flow Components
Next, let's discuss control flows. I think the praises of JSX already, and in all cases, this is going to be enough to cover your needs. However, the Solid team decided to add a couple of helper components in the library, which provides some better tooling for some of the most common problems. Take for instance Show component, which is pretty intuitive. Instead of using the inline && operator to conditionally render elements, you can use Show and have your code be a bit more clean and clear. In the same line, the Switch component allows you to map multiple possible outcomes by using the Match clauses. Also, the component provides a fallback option, so it's easier for you to logically group code together.
While we are at this topic, let's also use the For component to refactor our list of members. As the array changes, the For component updates or moves items in the DOM rather than recreating them.
Reason 5: Built-in State Management
It's time now to get serious and discuss one of the leading causes of headaches and frustrations for developers when building front-end apps: state management. Long story short, this was painful to handle until React introduced the Flux pattern. Then various third-party solutions with various degrees of complexity were developed. You'll find a wide range of state managers in the market, but Solid decided to take out the decision paralysis from the picture. So this despite its small size, the library comes with a store solution out of the box.
Solid stores are proxy objects whose properties can be tracked and can contain other objects which automatically became wrapped in proxies themselves. We can create a store using the createStore function, which takes an initial state, wraps it in a store, and returns a read-only proxy object and a setter function. The setter function is flexible as well. We can easily pass an object as the argument or a function that accesses the previous state and returns the new state. As a quick FYI, setting a value to undefined will delete the entry from the store.
Before moving on, I want to also mention the option to use the Context API to avoid passing data around as props. It is React inspired and it is useful for sharing signals and stores.
Bonus: createResource for Async Data
One of the basic use cases of web apps is exchanging data with a backend, usually through some sort of API. A nice little feature to help with this is the createResource utility function. Resources are special signals designed specifically to handle async loading, and their purpose is to wrap async values in a way that makes them easy to interact with. Solid's distributed execution model, this is the opposite to async/await or generators which provide sequential execution models.
Let's look at an example to clarify this use case. Usually, our members list will be populated from a server request. How would we do this in a traditional manner? Well, we'd probably use a lifecycle method like the onMount to run some code when the component is added to the DOM. Inside that component, we'd make a fetch call to the API, and when the response is received, the signal is updated via the setter. Now let's refactor this using createResource. This is extremely simple. Let's assign the members value to the result of the createResource function and we'll pass the HTTP call as the parameter. That's it. Convenient, right?
createResource can also be called with two arguments: a signal and an async fetch method. Whenever the signal is changed, the fetch method will be called again and the member detail is updated accordingly.
Okay, so these are the five great features of Solid, but there is another major topic I want to discuss before wrapping things up. This is also a good point to remind you to subscribe to this channel if you want to stay up to date on various topics in the dev world.
So SolidJS is great and all, but its ecosystem was missing one big piece: a meta-framework. For those who don't know, meta-frameworks are a set of libraries and tools bundled together in a final product aimed to improve both the app performance and the developer experience. React has Next, Vue has Nuxt, and now Solid has SolidStart. In the top right corner, I'm linking a video where I'm looking at SolidStart in more detail, but for this video, I'll just mention that it is a great framework that provides useful tools such as a routing solution, server-side rendering, a powerful CLI, and more.
If you found this video useful, please consider liking it. Until next time, thank you for watching.