Home > Blog > tech

SolidJS คืออะไร? Reactive Framework ที่เร็วกว่า React แบบไม่ต้อง Virtual DOM 2026

SolidJS Reactive Framework Guide 2026
2026-04-16 | tech | 3400 words

ในโลกของ Frontend Development ที่ React ครองตลาดมานาน มี Framework ใหม่ที่น่าสนใจอย่าง SolidJS ที่ท้าทาย React ด้วยแนวคิดที่แตกต่างอย่างสิ้นเชิง SolidJS ใช้ Fine-grained Reactivity โดยไม่ต้องพึ่ง Virtual DOM ทำให้ได้ Performance ที่เร็วกว่า React อย่างเห็นได้ชัดใน Benchmark ทุกตัว

บทความนี้จะสอน SolidJS ตั้งแต่พื้นฐาน แนวคิด Reactive Primitives ไปจนถึง SolidStart (Meta-framework) พร้อมเปรียบเทียบกับ React และ Svelte

SolidJS คืออะไร?

SolidJS เป็น JavaScript UI Library ที่สร้างโดย Ryan Carniato เปิดตัวเวอร์ชัน 1.0 ในปี 2021 SolidJS มีจุดเด่นที่:

ทำไม No Virtual DOM ถึงเร็วกว่า?

// React ทำงานอย่างนี้:
// 1. State เปลี่ยน
// 2. Re-render Component ทั้งตัว → สร้าง VDOM ใหม่
// 3. Diff เปรียบเทียบ VDOM เก่า vs ใหม่
// 4. Patch DOM จริง เฉพาะส่วนที่ต่าง
// → มีค่าใช้จ่าย (Cost) ในขั้นตอน 2, 3

// SolidJS ทำงานอย่างนี้:
// 1. Signal เปลี่ยน
// 2. อัปเดต DOM Node ที่ใช้ Signal นั้นโดยตรง
// → ข้ามขั้นตอน VDOM ทั้งหมด = เร็วกว่า

createSignal — State ของ SolidJS

createSignal คือ Reactive Primitive ตัวหลักของ SolidJS เทียบได้กับ useState ของ React แต่ทำงานต่างกันมาก:

import { createSignal } from "solid-js";

function Counter() {
  // createSignal คืน [getter function, setter function]
  const [count, setCount] = createSignal(0);

  // count() เป็น function ต้องเรียกด้วย ()
  // ต่างจาก React ที่ count เป็น value ตรงๆ

  return (
    <div>
      <p>Count: {count()}</p>
      <button onClick={() => setCount(count() + 1)}>+1</button>
      <button onClick={() => setCount(c => c - 1)}>-1</button>
    </div>
  );
}

// สิ่งที่ต่างจาก React:
// 1. count เป็น function ต้องเรียก count() ไม่ใช่ count
// 2. Component function ถูกเรียกแค่ครั้งเดียว! (ไม่มี Re-render)
// 3. เมื่อ count เปลี่ยน เฉพาะ <p> ที่แสดง count() จะอัปเดต
จุดสำคัญ: ใน SolidJS Component function ถูกเรียก แค่ครั้งเดียว ตอน Mount ไม่เหมือน React ที่ Re-run ทั้ง function ทุกครั้งที่ State เปลี่ยน นี่คือหัวใจของ Performance ที่ดี

createMemo — Computed Value

createMemo คือ Derived state ที่ Cache ผลลัพธ์ไว้ คำนวณใหม่เฉพาะเมื่อ Dependencies เปลี่ยน:

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

function ShoppingCart() {
  const [items, setItems] = createSignal([
    { name: "iPhone", price: 35000, qty: 1 },
    { name: "Case", price: 500, qty: 2 },
  ]);
  const [discount, setDiscount] = createSignal(0.1); // 10%

  // createMemo — คำนวณใหม่เมื่อ items() หรือ discount() เปลี่ยน
  const subtotal = createMemo(() =>
    items().reduce((sum, item) => sum + item.price * item.qty, 0)
  );

  const total = createMemo(() =>
    subtotal() * (1 - discount())
  );

  return (
    <div>
      <p>Subtotal: {subtotal().toLocaleString()} บาท</p>
      <p>Discount: {(discount() * 100)}%</p>
      <p>Total: {total().toLocaleString()} บาท</p>
    </div>
  );
}

createEffect — Side Effects

createEffect ทำงานเมื่อ Dependencies ที่ใช้ภายในเปลี่ยนแปลง (Auto-tracking):

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

function Logger() {
  const [name, setName] = createSignal("World");
  const [count, setCount] = createSignal(0);

  // Effect จะ Track dependencies อัตโนมัติ
  // เมื่อ name() เปลี่ยน → Effect จะ Re-run
  createEffect(() => {
    console.log(`Hello, ${name()}!`);
    // ไม่ Track count() เพราะไม่ได้ใช้ใน Effect นี้
  });

  // Cleanup (เหมือน useEffect return)
  createEffect(() => {
    const interval = setInterval(() => setCount(c => c + 1), 1000);
    // onCleanup ทำงานก่อน Effect Re-run หรือ Component Unmount
    onCleanup(() => clearInterval(interval));
  });

  return (
    <div>
      <input value={name()} onInput={(e) => setName(e.target.value)} />
      <p>Timer: {count()}</p>
    </div>
  );
}

createResource — Data Fetching

createResource เป็น Built-in primitive สำหรับ Async data fetching:

import { createResource, createSignal, Suspense } from "solid-js";

// Fetcher function
const fetchUser = async (id) => {
  const res = await fetch(`https://api.example.com/users/${id}`);
  return res.json();
};

function UserProfile() {
  const [userId, setUserId] = createSignal(1);

  // createResource(source signal, fetcher)
  // จะ Re-fetch เมื่อ userId() เปลี่ยน
  const [user, { refetch, mutate }] = createResource(userId, fetchUser);

  return (
    <div>
      <input
        type="number"
        value={userId()}
        onInput={(e) => setUserId(Number(e.target.value))}
      />

      <Suspense fallback={<p>Loading...</p>}>
        <Show when={user()} fallback={<p>No user found</p>}>
          <h3>{user().name}</h3>
          <p>Email: {user().email}</p>
        </Show>
      </Suspense>

      <button onClick={refetch}>Refresh</button>
    </div>
  );
}

Show / For / Switch — Control Flow Components

SolidJS ใช้ Control Flow Components แทน JavaScript expressions เพื่อ Optimize DOM updates:

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

function App() {
  const [loggedIn, setLoggedIn] = createSignal(false);
  const [items, setItems] = createSignal(["Apple", "Banana", "Cherry"]);
  const [status, setStatus] = createSignal("loading");

  return (
    <div>
      {/* Show — Conditional rendering */}
      <Show when={loggedIn()} fallback={<p>Please login</p>}>
        <p>Welcome back!</p>
      </Show>

      {/* For — List rendering (keyed by reference) */}
      <ul>
        <For each={items()}>
          {(item, index) => <li>{index() + 1}. {item}</li>}
        </For>
      </ul>

      {/* Switch/Match — Multi-condition */}
      <Switch fallback={<p>Unknown status</p>}>
        <Match when={status() === "loading"}>
          <p>Loading...</p>
        </Match>
        <Match when={status() === "error"}>
          <p>Error occurred!</p>
        </Match>
        <Match when={status() === "success"}>
          <p>Data loaded!</p>
        </Match>
      </Switch>
    </div>
  );
}

// ทำไมใช้ Show/For แทน {condition && ...} หรือ .map()?
// เพราะ Show/For ถูก Optimize สำหรับ Fine-grained reactivity
// - Show: Mount/Unmount DOM จริงๆ ไม่ Re-run Component
// - For: Track แต่ละ Item แยก อัปเดตเฉพาะ Item ที่เปลี่ยน
// - ternary (? :) ก็ใช้ได้ แต่ Show มีประสิทธิภาพกว่า

SolidStart — Meta-framework

SolidStart คือ Meta-framework ของ SolidJS เหมือน Next.js ของ React:

// สร้างโปรเจกต์ SolidStart
npm init solid@latest my-app
// เลือก "with SolidStart"

// โครงสร้างโปรเจกต์
my-app/
├── src/
│   ├── routes/
│   │   ├── index.tsx        // → /
│   │   ├── about.tsx        // → /about
│   │   ├── users/
│   │   │   ├── index.tsx    // → /users
│   │   │   └── [id].tsx     // → /users/:id
│   │   └── [...404].tsx     // → 404 page
│   ├── components/
│   └── app.tsx
├── app.config.ts
└── package.json

// SolidStart ให้:
// - File-based routing
// - SSR (Server-Side Rendering)
// - API Routes
// - Data fetching (createAsync, cache)
// - Middleware
// - Deployment adapters (Vercel, Netlify, Cloudflare, Node)

SolidStart Data Loading

// routes/users/[id].tsx
import { createAsync, cache } from "@solidjs/router";

// Cache function — ทำงานฝั่ง Server
const getUser = cache(async (id: string) => {
  "use server";
  const res = await fetch(`https://api.example.com/users/${id}`);
  return res.json();
}, "user");

export default function UserPage() {
  const params = useParams();
  const user = createAsync(() => getUser(params.id));

  return (
    <Suspense fallback={<p>Loading...</p>}>
      <Show when={user()}>
        <h1>{user().name}</h1>
        <p>{user().email}</p>
      </Show>
    </Suspense>
  );
}

Solid vs React — เปรียบเทียบ

คุณสมบัติSolidJSReact
ReactivityFine-grained (Signal-based)Coarse-grained (Re-render)
Virtual DOMไม่มีมี
Component Re-runครั้งเดียว (Mount)ทุกครั้งที่ State เปลี่ยน
Bundle Size~7 KB (gzip)~42 KB (gzip)
StatecreateSignal (getter fn)useState (value)
Derived StatecreateMemouseMemo
Side EffectscreateEffect (auto-track)useEffect (manual deps)
JSXCompiled to DOM opsCompiled to createElement
SyntaxJSX (คล้าย React มาก)JSX
Meta-frameworkSolidStartNext.js, Remix
Ecosystemเล็กแต่โตเร็วใหญ่มาก
Job Marketน้อยมากที่สุด
Performance (JS Framework Benchmark)อันดับ 1-3อันดับ 20+

Solid vs Svelte — เปรียบเทียบ

คุณสมบัติSolidJSSvelte
ApproachRuntime Reactive (เล็ก)Compiler-based (No Runtime)
ReactivityExplicit (createSignal)Implicit ($: reactive statements)
SyntaxJSX.svelte files (HTML-like)
Learning Curve จาก Reactง่ายมาก (JSX เหมือนกัน)ต้องเรียน Syntax ใหม่
TypeScriptFirst-class supportดีขึ้นมากใน Svelte 5
Performanceเร็วกว่าเล็กน้อยเร็วมาก
Meta-frameworkSolidStartSvelteKit
Communityเล็กกว่าใหญ่กว่า

Solid Store — Nested State Management

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

function TodoApp() {
  // createStore สำหรับ Nested/Complex state
  const [state, setState] = createStore({
    user: { name: "John", theme: "dark" },
    todos: [
      { id: 1, text: "Learn SolidJS", done: false },
      { id: 2, text: "Build app", done: false },
    ],
    filter: "all",
  });

  // อัปเดต Nested state ด้วย Path syntax
  const toggleTodo = (id) => {
    setState("todos", (todo) => todo.id === id, "done", (done) => !done);
  };

  // เพิ่ม Todo
  const addTodo = (text) => {
    setState("todos", (todos) => [
      ...todos,
      { id: Date.now(), text, done: false },
    ]);
  };

  // อัปเดต User theme
  const toggleTheme = () => {
    setState("user", "theme", (t) => (t === "dark" ? "light" : "dark"));
  };

  return (
    <div>
      <h2>Todos ({state.user.name})</h2>
      <For each={state.todos}>
        {(todo) => (
          <div>
            <input
              type="checkbox"
              checked={todo.done}
              onChange={() => toggleTodo(todo.id)}
            />
            <span style={{ "text-decoration": todo.done ? "line-through" : "none" }}>
              {todo.text}
            </span>
          </div>
        )}
      </For>
    </div>
  );
}

Routing ใน SolidJS

// ติดตั้ง @solidjs/router
npm install @solidjs/router

import { Router, Route, A } from "@solidjs/router";

// Routes
function App() {
  return (
    <Router>
      <nav>
        <A href="/">Home</A>
        <A href="/about">About</A>
        <A href="/users">Users</A>
      </nav>

      <Route path="/" component={Home} />
      <Route path="/about" component={About} />
      <Route path="/users/:id" component={UserDetail} />
      <Route path="*404" component={NotFound} />
    </Router>
  );
}

// Dynamic Route
import { useParams } from "@solidjs/router";

function UserDetail() {
  const params = useParams();
  // params.id จะ Reactive อัตโนมัติ
  return <h1>User: {params.id}</h1>;
}

เมื่อไหร่ควรเลือก SolidJS?

เลือก SolidJS ถ้าเลือก React ถ้า
ต้องการ Performance สูงสุดต้องการ Ecosystem ใหญ่ + Library เยอะ
Bundle size สำคัญต้องการหางานง่าย
รู้จัก React อยู่แล้ว อยากลองของใหม่ทีมส่วนใหญ่รู้จัก React
โปรเจกต์ใหม่ ไม่ต้องพึ่ง React Ecosystemต้องใช้ Library เฉพาะ React (เช่น React Native)
สนใจ Fine-grained Reactivityต้องการ Community support ใหญ่
ทำ SPA/Dashboard ที่ Performance criticalทำ Mobile app ด้วย React Native

สรุป

SolidJS เป็น Framework ที่น่าสนใจมากในปี 2026 ด้วย Fine-grained Reactivity ที่ให้ Performance สูงสุดในบรรดา JavaScript Frameworks ทั้งหมด ใช้ JSX Syntax ที่คุ้นเคยสำหรับ React Developer แต่ทำงานเร็วกว่ามากเพราะไม่มี Virtual DOM

ถ้าคุณเป็น React Developer ที่อยากลองสิ่งใหม่ SolidJS คือทางเลือกที่ดีที่สุด เรียนรู้ได้เร็ว (เพราะ JSX เหมือนกัน) แต่ได้ Performance ที่ดีกว่า เริ่มต้นวันนี้ด้วย npm init solid@latest แล้วคุณจะเข้าใจว่าทำไม Fine-grained Reactivity ถึงเป็นอนาคตของ Frontend Development


Back to Blog | iCafe Forex | SiamLanCard | Siam2R