ConfigsApr 11, 2026·1 min read

SolidJS — Simple & Performant Reactive UI Framework

SolidJS is a declarative JavaScript library for building user interfaces. Fine-grained reactivity, no virtual DOM, and performance that rivals vanilla JS. React-like syntax, 10x faster.

AI
AI Open Source · Community
Quick Use

Use it first, then decide how deep to go

This block should tell both the user and the agent what to copy, install, and apply first.

# Create a new Solid project
npx degit solidjs/templates/ts my-app
cd my-app
npm install
npm run dev

# Or with Solid Start (meta framework)
npm create solid@latest my-app
Intro

SolidJS is a declarative, efficient, and flexible JavaScript library for building user interfaces. It uses React-like JSX syntax but with a completely different runtime model based on fine-grained reactivity (like Svelte) instead of a virtual DOM. The result is performance that consistently ranks among the fastest frameworks in industry benchmarks, often indistinguishable from vanilla JavaScript.

With 35.4K+ GitHub stars and MIT license, SolidJS has become the go-to framework for developers who want React's developer experience with dramatically better runtime performance.

What SolidJS Does

  • Fine-Grained Reactivity: Updates exact DOM nodes instead of re-rendering components
  • No Virtual DOM: Compiled templates, direct DOM manipulation
  • React-like JSX: Familiar syntax for React developers
  • Signals: Primitive reactive state management built-in
  • SSR & SSG: Server-side rendering and static generation via Solid Start
  • Small Bundle: Core library is ~7KB gzipped
  • TypeScript First: Excellent type inference
  • Progressive: Use as a library or full meta-framework
  • Stores: Built-in nested reactive stores
  • Context: Dependency injection without re-renders

Architecture Difference

React:
  Component re-renders → Virtual DOM diff → DOM update
  (Whole component function runs on every change)

Solid:
  Signal changes → Specific DOM node updates
  (Component function runs ONCE, only reactive parts update)

This means in Solid, your component code runs once at mount, and only the specific reactive expressions update on state changes.

Basic Example

Counter

import { createSignal } from "solid-js";

function Counter() {
  const [count, setCount] = createSignal(0);

  // This console.log runs ONCE (at mount), not on every re-render
  console.log("Counter component setup");

  return (
    <div>
      <h1>Count: {count()}</h1>
      <button onClick={() => setCount(count() + 1)}>
        Increment
      </button>
    </div>
  );
}

Note: count() is called as a function (it's a getter). This is what enables Solid to track dependencies.

Derived State

import { createSignal, createMemo } from "solid-js";

function PriceCalculator() {
  const [price, setPrice] = createSignal(100);
  const [quantity, setQuantity] = createSignal(1);

  // Memo only recomputes when price or quantity changes
  const total = createMemo(() => price() * quantity());

  return (
    <div>
      <input
        type="number"
        value={price()}
        onInput={(e) => setPrice(+e.currentTarget.value)}
      />
      <input
        type="number"
        value={quantity()}
        onInput={(e) => setQuantity(+e.currentTarget.value)}
      />
      <p>Total: ${total()}</p>
    </div>
  );
}

Effects

import { createSignal, createEffect } from "solid-js";

function AutoSave() {
  const [text, setText] = createSignal("");

  createEffect(() => {
    // Runs whenever text() changes
    localStorage.setItem("draft", text());
    console.log("Saved:", text());
  });

  return (
    <textarea
      value={text()}
      onInput={(e) => setText(e.currentTarget.value)}
    />
  );
}

Control Flow Components

import { For, Show, Switch, Match } from "solid-js";

function UserList(props) {
  return (
    <div>
      {/* Conditional rendering - more efficient than && */}
      <Show when={props.users.length > 0} fallback={<p>No users</p>}>
        {/* Keyed list rendering */}
        <For each={props.users}>
          {(user) => (
            <div>
              <h3>{user.name}</h3>
              <Switch fallback={<p>Unknown status</p>}>
                <Match when={user.status === "active"}>
                  <span class="green">Active</span>
                </Match>
                <Match when={user.status === "pending"}>
                  <span class="yellow">Pending</span>
                </Match>
              </Switch>
            </div>
          )}
        </For>
      </Show>
    </div>
  );
}

Stores (Nested Reactivity)

import { createStore } from "solid-js/store";

function TodoApp() {
  const [state, setState] = createStore({
    todos: [],
    filter: "all",
    user: { name: "Anonymous", preferences: { theme: "light" } },
  });

  // Add todo - reactive update
  const addTodo = (text) => {
    setState("todos", state.todos.length, { id: Date.now(), text, done: false });
  };

  // Update nested property - only affects dependent components
  const toggleTheme = () => {
    setState("user", "preferences", "theme", (t) => t === "light" ? "dark" : "light");
  };

  // Filter todos - reactive
  const filteredTodos = () => {
    if (state.filter === "all") return state.todos;
    if (state.filter === "active") return state.todos.filter(t => !t.done);
    return state.todos.filter(t => t.done);
  };

  return (
    <div class={state.user.preferences.theme}>
      <button onClick={toggleTheme}>Toggle Theme</button>
      <For each={filteredTodos()}>
        {(todo) => <div>{todo.text}</div>}
      </For>
    </div>
  );
}

Solid Start (Meta Framework)

npm create solid@latest my-app

Features:

  • File-based routing: Like Next.js/Remix
  • Server functions: RPC-like server actions
  • SSR/SSG/CSR: Flexible rendering modes
  • Middleware: Request/response interceptors
  • Deployment: Vercel, Netlify, Cloudflare, Node
// routes/posts/[id].tsx
import { RouteDataArgs, useRouteData } from "@solidjs/router";
import { createServerData$ } from "solid-start/server";

export function routeData({ params }: RouteDataArgs) {
  return createServerData$(async ([id]) => {
    const post = await db.post.findUnique({ where: { id } });
    return post;
  }, { key: () => [params.id] });
}

export default function Post() {
  const post = useRouteData<typeof routeData>();

  return (
    <article>
      <h1>{post()?.title}</h1>
      <div innerHTML={post()?.content} />
    </article>
  );
}

Solid vs React vs Svelte

Feature SolidJS React Svelte Vue
Reactivity Signals (fine-grained) Virtual DOM Compiled Proxies
Bundle size ~7KB ~45KB ~2KB ~34KB
JS Framework Benchmark Top 3 Middle Top 5 Middle
JSX Yes Yes No Templates
Re-renders Component once On every change Compiled Reactive
Learning curve Easy (if React) Easy Easy Medium
Ecosystem Growing Massive Growing Large
TypeScript Excellent Good Good Excellent

Migration from React

Solid API is similar to React hooks:

// React
const [count, setCount] = useState(0);
useEffect(() => { console.log(count); }, [count]);
return <div>{count}</div>;

// Solid
const [count, setCount] = createSignal(0);
createEffect(() => { console.log(count()); });
return <div>{count()}</div>; // Note: count() as function call

Key differences:

  • Signals are getter functions: count() not count
  • No dependency arrays needed (automatic tracking)
  • Components don't re-render on state changes

常见问题

Q: Solid 为什么比 React 快? A: React 在每次状态变化时重新运行整个组件函数,然后通过 virtual DOM diff 找出变化。Solid 编译模板为直接的 DOM 操作,只在信号变化时更新具体的 DOM 节点,跳过所有 virtual DOM 的开销。

Q: 可以用 React 库吗? A: 不能直接使用 React 库(API 不同)。但 Solid 有自己的生态:Solid Router、Solid Query(类似 TanStack Query)、Solid UI 组件库。大部分常用库都有 Solid 版本。

Q: 适合大型项目吗? A: 适合。Solid 在生产环境已被许多公司使用。TypeScript 支持优秀,性能特别适合性能敏感场景(dashboards、数据可视化、实时应用)。生态系统比 React 小但足够完整。

来源与致谢

Discussion

Sign in to join the discussion.
No comments yet. Be the first to share your thoughts.

Related Assets