Solid.js: From Zero to Sarcastic Hero in Under 30 Minutes
Alright, so you’re thinking about jumping on the Solid.js bandwagon? Excellent. Or maybe terrible. Time will tell. Either way, let’s get this over with quickly. Solid.js is a JavaScript framework for building user interfaces, and it boasts performance that makes React developers weep quietly into their coffee1. Let’s see if it lives up to the hype.
Why Solid.js? (Or, Why Bother?)
In a world drowning in JavaScript frameworks, Solid.js dares to be different. It uses fine-grained reactivity, which means it surgically updates the DOM only when absolutely necessary. No virtual DOM bloat here. It’s like comparing a sniper rifle to a shotgun2.
“SolidJS excels in performance due to its fine-grained reactivity model. It often outperforms React in benchmarks, especially in scenarios with intensive UI …”
If you’re tired of performance bottlenecks and want something that feels more like vanilla JavaScript, Solid.js might just be your cup of lukewarm tea.
Setting Up (The Agony Begins)
First, make sure you have Node.js installed. If you don’t, stop now and reconsider your life choices. Then, open your terminal and type:
npm create solid my-appcd my-appnpm install
Or, if you’re a hipster who prefers Yarn:
yarn create solid my-appcd my-appyarn install
This will scaffold a new Solid.js project. The file structure is fairly straightforward, even for those of you who still think jQuery is modern.
”Hello, World” (The Bare Minimum)
Open src/App.jsx
and replace the existing code with this:
import { render } from 'solid-js/web';import { createSignal } from 'solid-js';
function App() { const [name, setName] = createSignal('World');
return ( <> <h1>Hello, {name()}!</h1> <input type="text" value={name()} onChange={e => setName(e.target.value)} /> </> );}
render(() => <App />, document.getElementById('root'));
This does the following:
- Imports
render
andcreateSignal
fromsolid-js
. - Creates a signal called
name
with an initial value of “World”. Signals are how Solid.js tracks changes. - Renders an
h1
element that displays “Hello, World!”, and updates as you type in the input box.
Components (Because Reusing Code is a Thing)
Components are reusable UI elements. Create a new file called src/MyComponent.jsx
:
import { Component } from 'solid-js';
interface MyComponentProps { text: string;}
const MyComponent: Component<MyComponentProps> = (props) => { return ( <p>The text is: {props.text}</p> );};
export default MyComponent;
Then, import and use it in App.jsx
:
import { render } from 'solid-js/web';import { createSignal } from 'solid-js';import MyComponent from './MyComponent';
function App() { const [name, setName] = createSignal('World');
return ( <> <h1>Hello, {name()}!</h1> <input type="text" value={name()} onChange={e => setName(e.target.value)} /> <MyComponent text={"Some dynamic text: " + name()} /> </> );}
render(() => <App />, document.getElementById('root'));
Solid.js components are simple JavaScript functions that return JSX. Props are passed as arguments. If you’re coming from React, this will feel vaguely familiar, but without all the extra baggage.
Reactivity (The Guts of It)
Solid.js uses signals, effects, and memos for reactivity. Signals hold values, effects react to signal changes, and memos cache computed values. It’s all very efficient3.
import { render } from 'solid-js/web';import { createSignal, createEffect } from 'solid-js';
function App() { const [count, setCount] = createSignal(0);
createEffect(() => { console.log('Count changed:', count()); });
return ( <> <h1>Count: {count()}</h1> <button onClick={() => setCount(count() + 1)}>Increment</button> </> );}
render(() => <App />, document.getElementById('root'));
Each time the count
signal changes, the createEffect
runs, logging the new value. This is fine-grained reactivity in action. Only what needs to update, updates4.
Testing (Because Bugs Are Inevitable)
Testing Solid.js components isn’t much different from testing any other JavaScript code. You can use tools like Jest, Vitest, or Testing Library. Here’s a basic example using Vitest:
First, install Vitest:
npm install -D vitest @testing-library/solid
Then, create a test file, e.g., src/App.test.jsx
:
import { render, screen } from '@testing-library/solid';import App from './App';
test('renders hello world', () => { render(() => <App />); const linkElement = screen.getByText(/Hello, World!/i); expect(linkElement).toBeInTheDocument();});
Add a test script to your package.json
:
"scripts": { "test": "vitest"}
Run the tests:
npm test
This sets up a basic test that renders the App
component and checks if the “Hello, World!” text is present. Adapt as needed.
Deployment (Releasing Your Masterpiece)
Deploying a Solid.js app is fairly straightforward. Since it compiles to static assets, you can deploy it on any static hosting service like Netlify, Vercel, or even AWS S35.
Here’s how to deploy to Netlify:
- Build your app:
npm run build
- Install the Netlify CLI:
npm install -g netlify-cli
- Deploy to Netlify:
netlify deploy --prod --dir=dist
This will deploy your app to Netlify. Congratulations, you’re now live.
Advanced Component Patterns
For those of you who like to make things more complicated than they need to be, Solid.js offers some advanced component patterns. Let’s dive into a few, shall we? These patterns aim to improve readability and flexibility, because apparently, writing code that just works isn’t enough anymore.
List-Like Components
This pattern is useful when you want to pass an array of data and render a child template. Instead of passing the tabs as props, you can use children to define the tabs6.
import { children, Component, createSignal, For, JSXElement } from 'solid-js'
interface TabsProps { children: JSXElement}
export const Tabs: Component<TabsProps> = (props) => { const [activeTab, setActiveTab] = createSignal<number>(0)
const tabs = children(() => props.children) const evaluatedTabs = () => tabs.toArray() as unknown as TabProps[]
return ( <div> <ul> <For each={evaluatedTabs()}> {({ title }, index) => ( <li> <button onClick={() => setActiveTab(index())}>{title}</button> </li> )} </For> </ul> <div>{evaluatedTabs()[activeTab()].children}</div> </div> )}
interface TabProps { title: string children: JSXElement}export const Tab: Component<TabProps> = (props) => { return props as unknown as JSXElement}
Usage:
<Tabs> <Tab title="Tab 1">Tab 1</Tab> <Tab title="Tab 2">Tab 2</Tab></Tabs>
Declarative Slots
This pattern allows you to pass multiple JSXElement
to a component and render them in different places. Instead of passing elements as props, you can use slots to define where the elements should be rendered7.
import { children, Component, createComputed, JSXElement, on } from 'solid-js'import { createStore } from 'solid-js/store'
export const getSlots = (_children: JSXElement) => { const parts = children(() => _children) const [slots, setSlots] = createStore<Record<string, JSXElement>>({}) createComputed( on(parts, () => { for (const part of parts.toArray() as unknown as SlotProps[]) { if (!part.name) { setSlots('default', () => part) continue } setSlots(part.name, () => part.children) } }) ) return slots}
interface SectionProps { children: JSXElement}
export const Section: Component<SectionProps> = (props) => { const slots = getSlots(props.children)
return ( <section> <header class="bg-black text-white p-5">{slots.header}</header> <div class="p-5">{slots.default}</div> </section> )}
interface SlotProps { name: string children: JSXElement}export const Slot: Component<SlotProps> = (props) => { return props as unknown as JSXElement}
Usage:
<Section> <Slot name="header"> <h3>My Header</h3> </Slot> My Content</Section>
Conclusion (The End?)
Solid.js is a fast, efficient, and relatively painless way to build user interfaces. It’s not a silver bullet, but it’s a damn good option if you’re tired of the usual suspects. Now, go forth and create something… or just complain about JavaScript frameworks on Twitter. Your call.
Footnotes
-
“The future of solid looks a lot brighter than that of React IMO. The performance of perfectly optimally memoized React is still a lot slower …” (https://reddit.com/r/solidjs/comments/1b3a4cs/future_of_solidjs, 2025-03-08T09:26:48.000Z) ↩
-
SolidJS is a modern declarative JavaScript library for UI component development. It offers a high-performance option for developing dynamic user interfaces. (https://aalpha.net/blog/solidjs-vs-react-comparison, 2024-12-27T13:09:53.000Z) ↩
-
Solid’s reactivity is built on signals that are automatically tracked to appropriately trigger effects and UI updates. (https://aalpha.net/blog/solidjs-vs-react-comparison, 2024-12-27T13:09:53.000Z) ↩
-
SolidJS’ performance comes from appropriately scaled granularity through compilation, the most effective DOM creation methods, a reactive system not limited to … (https://aalpha.net/blog/solidjs-vs-react-comparison, 2024-12-27T13:09:53.000Z) ↩
-
Are you ready to deploy your Solid application? Follow our guides for different deployment services. Cloudflare · Firebase · AWS with Flightcontrol. (https://solidjs.com/guides/deploying, 2025-03-08T09:26:49.000Z) ↩
-
This post explains how to write more readable declarative components in solidjs. (https://raqueeb.com/blog/2023/03/15/3-patterns-to-write-better-and-more-readable-solidjs-components, 2025-02-19T17:42:41.000Z) ↩
-
This post explains how to write more readable declarative components in solidjs. (https://raqueeb.com/blog/2023/03/15/3-patterns-to-write-better-and-more-readable-solidjs-components, 2025-02-19T17:42:41.000Z) ↩