Choosing the correct JavaScript framework is crucial for the success of your web development project in today’s fast-paced world. With a lot of options, deciding on the most suitable one for your needs can be confusing.
With ReactJS being released in 2013 it should not be much of a surprise that it’s more popular than SolidJS which was first open-sourced in 2018 and officially had version 1.0 released in 2021, making it roughly 5 years younger than ReactJS. But SolidJS is faster and efficient then ReactJS in almost all the metrics.
So what is SolidJS?
SolidJS is a modern frontend library that focuses on performance and fine-grained reactivity which means that it will not re-render the components every time a state updates but will track the functions and blocks using a dependency and update or execute that part only. Therefore it doest not use a virtual DOM but instead makes use of a compiler to track and update the reactive parts of your components.
On the surface, SolidJS and ReactJS appear to be closely related. Both SolidJS and ReactJS use JSX for templating (HTML in JS) and use hooks, functional components. SolidJS follows the same philosophy as ReactJS, with unidirectional data flow, read/write segregation and immutable interfaces.
But in browser, both manipulate page’s HTML elements (DOM) differently to deliver the desired user experience. ReactJS uses virtual dom and diffing algorithm to update dom on state update and SolidJS use reactive primitives (proxies) to manage state and use its compiler to update dom thus does not require a virtual dom.
A Brief Comparison
Feature | ReactJS | SolidJS |
---|---|---|
TypeScript support | ✅ | ✅ |
Declarative nature | ✅ | ✅ |
Unidirectional data flow | ✅ | ✅ |
JSX first-class support | ✅ | ✅ |
Direct manipulation of the DOM | ❌ | ✅ |
Avoids component re-rendering | ❌ | ✅ |
Highly performant | ❌ | ✅ |
Rich community and ecosystem | ✅ | ❌ |
Excellent developer documentation | ✅ | ✅ |
Scaffolding tools | ✅ | ✅ |
Conditional rendering | ✅ | ✅ |
Server-side rendering (i.e., hydration) | ✅ | ✅ |
Concurrent rendering (i.e., suspense) | ✅ | ✅ |
Now we’ll go into more detail on the similarities and differences between ReactJS and SolidJS.
Starting a new project
The most critical part of adopting any frontend framework is its ease of use. No matter how performant a framework is, If using it to create a new project is too complex, its adoption in the frontend ecosystem will be slow.
Creating a new ReactJS project
ReactJS has different options for creating a new project, including create-react-app, Vite and a manual setup using Webpack. The most widely used is create-react-app
. You can read more about this topic here. With Node.js installed on your computer, you can run this command on your terminal to create a new React project using create-react-app
:
> npx create-react-app react-app
This will generate a new react application named react-app with webpack as the build tool and npm as the default package manager.
Creating a new SolidJS project
You can use SolidJS Vite Templates to create a new app. To create your new SolidJS app, run following commands on your terminal:
> npx degit solidjs/templates/js my-app
> cd my-app
> npm i # or yarn or pnpm
This will generate a new SolidJS app named my-app with npm as the package manager and Vite as the build tool.
Now you can use npm run dev
to run the local server.
Component Structure
Components are one of the fundamental building blocks of modern frontend frameworks. React and SolidJS have exactly the same programmatic structures and support for components (individual, reusable pieces of code). SolidJS components look very similar to React functional components, and they both use JSX, the popular HTML-like syntax extension to JavaScript.
React and SolidJS offer the same components, but each framework has a unique rendering approach. React components render every time (barring memoization use), while SolidJS components only render once.
//SolidJS component
import Component from "./Component"
function App() {
return (
<div>
<h1>Solid Application</h1>
<Component />
</div>
)
}
export default App
//ReactJS component
import Component from "./Component"
function App() {
return (
<div>
<h1>React Application</h1>
<Component />
</div>
)
}
export default App
As you can see basic structure of both components is same. Also both use props the same way. The only difference is Solid does not allow prop destructuring as it loses the reference of the state variable due to this.
State Management
State refers to the data that frontend app use to either show on UI or do some action on. States are meant to change on user interaction and update the UI accordingly. State can be both global (available throughout the app) and local(available to a specific component).
State Management in ReactJS
For local state management in individual components, React use useState
hook. Hooks are basically functions intended to run when triggered by the framework at specific times. For eg. useState function will run whenever component re-render and keeps track of the value you set using setter method. Under the hood useState
hook use Closures to achieve this. Apart form this we can use useRef
hook also to store the data but this is not going to trigger the re-render of the function.
State Management in SolidJS
SolidJs also use similar approach to manage state called createSignal
. It looks similar to react
but is very different fundamentally. createSignal
method returns an array of two functions [getter,setter] = createSignal()
which we can call to get and set the value. On the other hand, the SolidJS createSignal
method can be used outside a component, so it’s easy to export it like any other variable and import it in any component it’s needed. This makes handling global state straightforward in SolidJS.
Apart from this SolidJs also have a concept of derived Signal where you can do the operations on the the existing state to return a new value which will change every time state updates.
A function that accesses a signal is effectively also a signal: when its wrapped signal changes it will in turn update its readers.
const [count, setCount] = createSignal(0) //Signal
const doubleCount = () => count() * 2 // Derived Signal
Side Effects
React use useEffect
hook to trigger side-effects on state change. useEffect hooks accepts a callback function and a dependency array. An empty dependency array means effect callback will run only once on component mount. We can also return a cleanup function
from the callback which react is going to run every-time before re-calling the functions and at last on component unmount.
useEffect(() => {
const connection = createConnection(serverUrl, roomId)
connection.connect()
return () => connection.disconnect()
}, [roomId])
Above useEffect callback will run on component mount and after that every time roomId change. That’s why it is preferred to pass primitive data types in dependency array as objects, arrays as react uses referential equality to check whether these complex values have changed.
To make sure object is created only when required we can use useMemo
hook which returns the same value and reference until a value in dependency array change.
In case of functions we should use useCallback
hook which again is going to return same function reference until a value in dependency array change.
In SolidJS an effect can be created by importing createEffect
from solid-js and providing it a function. The effect automatically subscribes to any signal that is read during the function’s execution and reruns when any of them change. This means that we just need to use the state getter function inside the createEffect and sold will take care of the rest.
const [count, setCount] = createSignal(0)
createEffect(() => {
console.log("The count is now", count())
})
The above callback function inside create effect will reruns whenever count changes.
Memoization
React depends on memoization for its applications to render quickly so it provides different memoization techniques from component memoization to functions memoization. Its important in react to use these as react will re-render components on state update and its upto us to figure out if we want to re-render a component, calculate a value or initialize a function on state update or not.
memo
memo is a higher order function which takes a component as first param and a callback function with boolean return value in second param. If you don’t pass second param react will shallow compare the current and previous props to determine if to render a component or not.
function MyComponent(props) {
/* render using props */
}
function areEqual(prevProps, nextProps) {
/*
return true if passing nextProps to render would return
the same result as passing prevProps to render,
otherwise return false
*/
//true means component will not re-render
//false means component re-render.
//This is the inverse from shouldComponentUpdate.
}
export default React.memo(MyComponent, areEqual)
Unlike the
shouldComponentUpdate()
method on class components, theareEqual
function returnstrue
if the props are equal andfalse
if the props are not equal. This is the inverse fromshouldComponentUpdate
.
useCallback
useCallback
hook lets you cache a function definition between re-renders. Means if you are passing a function down to a component which is using memo the component will still re-render on parent re-render as you are creating new definition of the passed function. In that case you can you useCallback
hook that let’s you cache the function reference between re-renders.
const cachedFn = useCallback(fn, dependencies)
useMemo
useMemo
lets you cache the result of a calculation between re-renders. So if you are doing some very expensive operation to get a value on component render you can use this hook to cache the value so that if any dependency updates that only function will run to calculate the value.
const cachedValue = useMemo(calculateValue, dependencies)
SolidJS createMemo
SolidJS manages memoization through a single method called createMemo
. This method keeps track on any signal or derived state used and run only when any value updates.
const [count, setCount] = createSignal(0)
const cachedData = createMemo(() => {
//some expensive operations using count()
console.log(count())
})
Is SolidJS Better Than ReactJS?
Deciding whether to learn SolidJS or ReactJS depends on several factors you want to prioritize in your web app or web development journey.
SolidJS outperforms ReactJS in terms of performance and user-friendliness. Although it shares similarities with React, SolidJS has distinct implementation differences. For instance, state management in SolidJS is more straightforward, and its rendering and DOM update mechanisms are faster than those of ReactJS. Additionally, SolidJS offers a wide range of built-in functionalities that would require external libraries in ReactJS.
However, SolidJS being a relatively new framework, hasn’t gained the same level of adoption and ecosystem size as ReactJS. Therefore, it may be easier to find third-party packages and integrations that are compatible with ReactJS rather than SolidJS.
Furthermore, resources for learning and problem-solving are more readily available for ReactJS on websites like Stack Overflow and programming blogs. Additionally, if you’re looking for job opportunities in web development, ReactJS currently has a larger job market than SolidJS.
Ultimately, learning SolidJS should not pose a challenge for those who have already learned React because SolidJS offers a simpler syntax compared to React and use things similar to react like JSX
, States
, Effects
, Memos
.