This article details how to use signals in Solid, a modern reactive JavaScript library for building user interfaces that rely primarily on components.
content:
- Introducing Signals
- What is a solid?
- What exactly are signals?
- signal example
- Angular signals
- Other Features of Solids
Introducing Signals
One of the latest trends in web development is signal, which provides a more reactive approach to updating values in your program that are subject to change. When a value is updated, everything using that value will also be updated. This is what makes Signal so unique.
The growth of signals and interest in them is reminiscent of all the hype that ushered in version 16.8 of React in 2019 when the React team introduced hooks.Purpose of hook The idea was to make the state update (and eventually all updates) approach more functional and stop using classes. Signals look much like hooks, but there are some subtle differences that set them apart (explained below).
where the signal is used
What is a solid?
Solid (also known as SolidJS) was created by Ryan Carniato in 2016 and released in 2018. js”
He wasn’t a fan of the direction that libraries such as React and Vue were taking at the time, but “preferred the control and configurability that came from using primitives that were smaller and independent of components. ” His solution was to create Solid. Solid is a reactive framework that uses signals to create fine-grained reactivity. This is a pattern of signals that we see in many other frameworks as well.
At first glance, Solid looks a lot like React with hooks and functional components. Both share the same philosophy when it comes to data management, so if you’re familiar with React, you’ll find Solid easy to learn.
However, there are some important differences.
- Solid is pre-compiled in a similar way to Svelte. This means that performance improvements are built into the final build, thus less code has to be shipped.
- Solid does not use virtual DOM. Components are just functions like React, but they are called only once the first time they are rendered. (In React, it’s called whenever that component updates.)
What exactly are signals?
signal Based on the observer pattern. This is one of the classic Gang of Four design patterns. In fact, Knockout uses something very similar to signals called “observables”.
Signals are the most atomic part of reactive applications. These are observable values that have an initial value and provide getter and setter methods that can be used to display or update this value, respectively. However, to get the most out of the signal, reactionThis is an effect that subscribes to a signal and executes according to its value change.
When a signal’s value changes, it effectively emits an event (or “signal”) and triggers a reaction (or “effect”). This is often a call to update and render components that depend on this value.These ingredients are said to Subscribe to the signal. This means that only these components are updated when the signal’s value changes.
A key concept of Solid is all View rendering is also an effect. Each signal is very closely tied to the specific component it affects. This means that views can be re-rendered in a very fine-grained way when values change without costly re-rendering the entire page.
signal example
To create a signal in Solid, createSignal
Call a function and assign two variables to its return value. Do the following:
const [name, setName] = createSignal("Diana Prince");
These two variables represent getter and setter methods. In the example above, name
is a getter and setName
It’s a setter.The value of the 0
it is passed to createSignal
Represents the initial value of the signal.
For React developers, this is of course familiar. Here is the code for creating something similar using React hooks.
const [name, setName] = useState("Diana Prince");
In React, getters (name
) are variables and setters (setName
) is a function.
However, while they look very similar, the main differences are: name
They behave like variables in React, but are functions in Solid.
have name
as a function means that when called within an effect, it automatically subscribes the effect to the signal. This means that when the value of the signal changes, the new value will be used to perform the effect.
Here is our example name()
signal:
createEffect(() => console.log(`Hello ${name()}`))
of createEffect
Functions can be used to perform effects based on a signal’s value, such as logging the value to the console. Subscribes to all signals referenced within the function. When the value of the signal changes, the effect code runs again.
In this example, name
signal using setName
When you use the setter function, you can see that the effect code runs and logs the new name to the console.
setName("Wonder Woman")
Having a getter as a function also means that the latest current value is always returned, but other frameworks often return “old” values even after they’ve been updated. It also means that any signal can be easily bound to a computed value and memoized.
const nameLength = createMemo(() => name().length)
This creates a read-only signal that can be accessed using: nameLength()
When the value of . changes, its value is updated. name
signal.
if name()
If a signal is included in a component, the component will automatically subscribe to this signal and re-render when its value changes.
import { render } from "solid-js/web"
import { createSignal } from "solid-js"
const HelloComponent = () => {
const [name, setName] = createSignal("Diana Prince");
return <h1>Hello {name()}</h1>
}
render(() => <HelloComponent />, document.getElementById("app"));
update the value of name
signal to use setName
Result is HelloComponent
re-rendering. moreover, HelloComponent
The function is called only once to create the associated HTML. Once called, it doesn’t need to be run again even if the value is updated. name
signal. In React, however, component functions are called whenever the value they contain changes.
Another big difference with Solid is that it doesn’t use the virtual DOM at all, even though it uses JSX for the view logic. Instead, compile your code ahead of time using the latest Vite build tools. This means that much less JavaScript needs to be shipped, and it doesn’t require the actual Solid library to ship (in much the same way as Svelte). Views are created in HTML. Then use a system of template literals to identify changes and perform good old DOM manipulations to make fine-grained updates on the fly.
These isolated, fine-grained updates to specific regions of the DOM are very different from React’s approach of completely rebuilding the virtual DOM after changes. Updating the DOM directly reduces the overhead of maintaining a virtual DOM and is much faster. Solid actually has some pretty impressive stats when it comes to rendering speed. He is second only to vanilla JavaScript.
All benchmarks can be viewed here.
Angular signals
As mentioned earlier, Angular recently adopted signals for fine-grained updates. They work similarly to Solid signals, but are created a little differently.
To create the signal, signal
A function is used and the initial value is passed as an argument.
const name = signal("Diana Prince")
The variable name to which the signal is assigned (name
) in the example above can be used as a getter.
console.log(name)
<< Diana Prince
to the signal set
A method you can use to update that value, like this:
name.set("Wonder Woman")
console.log(name)
<< Wonder Woman
The fine-grained approach to updates in Angular is almost identical to that in Solid.First, Angular has update()
A method that works like set
but derives the value instead of replacing it.
name.update(name => name.toUpperCase())
The only difference here is that it takes a value (name
) as a parameter and execute an instruction on it (.toUpperCase()
). This is very useful when you don’t know the final value that the getter replaces and need to derive it.
Second, Angular has computed()
A function that creates a memoized signal. Works exactly like Solid. createMemo
:
const nameLength = computed(() => name().length)
Similar to Solid, when it detects that the value of the signal in the computational function has changed, so does the value of the computed signal.
Finally, Angular has effect()
works exactly the same as createEffect()
Works on solids. The side effects are re-executed each time the dependent value is updated.
effect(() => console.log(`Hello`, name()))
name.update(name => name.toUpperCase())
Other Features of Solids
Signals aren’t the only thing Solid is notable for. As already mentioned, both creating and updating content is very fast. It also has an API very similar to React, so it should be easy to understand for anyone who has used React. However, Solid works in a very different way under the hood and is usually more performant.
Another cool feature of Solid is that it adds some nifty touches to JSX, such as control flow. can be used to create a for loop. <For>
You can include errors within your component using <ErrorBoundary>
.
moreover, <Portal>
Components are also useful for presenting content outside the normal flow (such as modals).and nested reactivity A change to an array or object of values means re-rendering the portion of the view that has changed, rather than re-rendering the entire list. Solid makes this even easier with stores. Solid will also support server-side rendering, hydration and streaming out of the box.
For those who want to try Solid, Solid’s website has a great introductory tutorial, and you can try out the code in the Solid playground.
Conclusion
This article introduced the concept of signals and how they are used in Solid and Angular. We also explored how Solid can help perform fine-grained updates to the DOM without requiring a virtual DOM. With many frameworks now adopting the signal paradigm, these are definitely tricks worth our wielding!