In the world of frontend JavaScript frameworks, we continue to see new innovations that enable better development experiences and more performant applications.
On one hand, there are frameworks and libraries like Vue, React, and Angular that allow you to declaratively define your UI with updates being optimized by a Virtual DOM, ensuring that only necessary updates are made. On the other hand, there are frameworks like Svelte and SolidJS, which moved away from shipping a framework and running a virtual DOM to instead compiling declarative UI into standard JavaScript, resulting in smaller bundles, faster speeds, and more granular reactivity using observables.
The latter type of framework has picked up big momentum since Vercel hired Svelte creator Rich Harris to work on Svelte full time, along with Netlify hiring SolidJS creator, Ryan Carniato, to do the same with SolidJS.
Recently, another framework has come to the party, Voby, which is inspired by many of the ideas of SolidJS but with a few differences. Voby was primarily intended to serve as the framework for building the author’s note taking app, Notable. In this article, we’ll compare Voby with SolidJS to see what Voby brings to the table. Let’s get started!
One of the most noticeable differences from framework to framework is the syntax for describing each UI and its reactivity.
SolidJS uses JSX for expressing UI and Hooks for creating reactivity through a custom observables implementation. In comparison, Svelte uses RXJS for observables. In SolidJS, a simple counter component would look like the following:
import { createSignal } from "solid-js"; function Counter(props) { const [count, setCount] = createSignal(0) return <div onClick={() => setCount(count() + 1)}>{count()}</div>; }
Using JSX does require a build step, and SolidJS has many optimizations that occur during this build step. However, if you really want to avoid building, you can opt to use lit-html or HyperScript template literals.
Also, you can see that in SolidJS, reactivity is handled by signals, which are observable values using Solid’s custom observable implementation. All JSX expressions are assumed to be effects in SolidJS. These signals can be used in effects, so whenever a signal used in the effect updates, the effect will re-run. Or, in our case, the effect will rebuild the UI from the JSX expression. The API for signals is very similar to React state where you have the value as well as a setter function for value. You don’t change the value directly.
Voby also uses observables using a library called Oby. Voby uses JSX as well, but it can also use HTM as an alternative, which is a mix of JSX, HyperScript, and lit-html in one syntax. Below is an example of a simple Voby counter component using HTML:
import {html} from 'voby'; const Counter = (): JSX.Element => { const value = $(0); const increment = () => value ( prev => prev + 1 ); return html` <p onClick=${increment}>${value}</p> `; };
Voby handles reactivity a little differently than SolidJS. Reactive values are defined using the $()
function. Instead of getting the value and a setter, you get a single function that acts like both a getter and setter. When passed an argument, it will set the value. In the html
tagged template literals, if an observable value is used inside of it, it will update whenever the value updates.
Instead of relying on array.map
and JavaScript for a lot of control flow logic like React, both SolidJS and Voby have built-in control flow components that are easier to use with under the hood optimization, meaning you don’t have to worry about key props.
In SolidJS, you would use the Show
component for conditional rendering:
<Show when={state.count > 0} fallback={<div>Loading...</div>}> <div>My Content</div> </Show>
If the when
prop is true
, the Show
components will render the UI in the child expression. If not, it will render the value in the fallback
prop.
On the other hand, Voby has an If
component:
<If when={visible}> <p>Hello!</p> </If>
The If
component works pretty much like the SolidJS Show
component, rendering the UI in the child expression if the When
prop is true
.
To loop over arrays of data in React, we’d have to rely on the array.map
method and make sure to pass a unique key prop to allow the virtual DOM to optimize updates. In SolidJS and Voby, we don’t have to worry about either the key prop or using map
.
SolidJS has the For
component, which takes the array as the each
prop:
<For each={state.list} fallback={<div>Loading...</div>}> {(item) => <div>{item}</div>} </For>
In case the data isn’t available yet, you can pass a fallback
expression.
Voby also has a For
component. It basically works the same as the For
component in SolidJS, but instead of an Each
prop, it uses a value
prop to define the array to be looped over:
<For values={numbers}> {( value ) => { return <p>Value: {value}</p> }} </For>
The SolidJS Switch
component will look through each nested Match
component and render the first one with a when
prop that is true
. If no Match
is rendered, then the fallback
prop on the Switch
is rendered:
<Switch fallback={<div>Not Found</div>}> <Match when={state.route === "home"}> <Home /> </Match> <Match when={state.route === "settings"}> <Settings /> </Match> </Switch>
Voby uses Switch
and Switch.case
:
<Switch when={value}> <Switch.Case when={0}> <p>0, the boundary between positives and negatives! (?)</p> </Switch.Case> <Switch.Case when={1}> <p>1, the multiplicative identity!</p> </Switch.Case> <Switch.Default> <p>{value}, I don't have anything interesting to say about that :(</p> </Switch.Default> </Switch>
The Voby Switch
works more like a traditional JavaScript switch statement in that a value is specified and tested against a bunch of different cases, and the code in matching cases is run. In this case, the value is specified in the when
prop in the Switch
, and the cases are in the when
prop of each Switch.Case
.
Although Voby executes on many of the ideas and principles of SolidJS, it is still in its early stages. Therefore, it doesn’t have support for server-side rendering or other features available in the production ready SolidJS. However, seeing the Notable app in action makes me optimistic for what is to come.
Voby works well in creating a performant and reactive application, so it’s definitely something to keep an eye on in the frontend framework space. I hope you enjoyed this article, and be sure to leave a comment if you have any questions. Happy coding!
There’s no doubt that frontends are getting more complex. As you add new JavaScript libraries and other dependencies to your app, you’ll need more visibility to ensure your users don’t run into unknown issues.
LogRocket is a frontend application monitoring solution that lets you replay JavaScript errors as if they happened in your own browser so you can react to bugs more effectively.
LogRocket works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app’s performance, reporting metrics like client CPU load, client memory usage, and more.
Build confidently — start monitoring for free.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowBuild scalable admin dashboards with Filament and Laravel using Form Builder, Notifications, and Actions for clean, interactive panels.
Break down the parts of a URL and explore APIs for working with them in JavaScript, parsing them, building query strings, checking their validity, etc.
In this guide, explore lazy loading and error loading as two techniques for fetching data in React apps.
Deno is a popular JavaScript runtime, and it recently launched version 2.0 with several new features, bug fixes, and improvements […]
One Reply to "Comparing SolidJS and Voby"
So, tell me one thing more, how SolidJS is safe for decentralized storage?