โหมดมืด
บทที่ 0 — React คืออะไร + JS/TS Essentials (พื้นฐาน JavaScript/TypeScript ที่ต้องรู้)
🟢 ระดับ: มือใหม่ — เริ่มที่บทนี้ได้เลย ไม่ต้องมีพื้นฐาน React มาก่อน
ก่อนจะลงโค้ดจริง บทนี้จะตอบคำถาม:
- ปัญหาของการเขียน UI แบบ "เปล่า ๆ" (vanilla JS — JS ดิบ ๆ ไม่ผ่าน framework / jQuery — library JS ยุคเก่าที่ช่วยย่อโค้ดการแก้ DOM) คืออะไร?
- React แก้ปัญหานี้ยังไง? — component (ชิ้นส่วน UI), Virtual DOM (DOM จำลองใน memory), declarative (เชิงประกาศ) (ทั้ง 3 คำจะอธิบายในหัวข้อถัดไป)
- ทบทวน JavaScript modern ที่ต้องรู้ก่อนเขียน React
- TypeScript essentials — รู้แค่เท่านี้ก็เริ่มได้
1. ปัญหาก่อน React — ทำไม UI ใหญ่ ๆ เจ็บปวด
1.1 ทำ UI ด้วย vanilla JS
สมมติเราจะทำ counter:
html
<div>
<p id="count">0</p>
<button id="inc">+</button>
<button id="dec">-</button>
</div>
<script>
let count = 0;
const countEl = document.getElementById('count');
document.getElementById('inc').addEventListener('click', () => {
count++;
countEl.textContent = count;
});
document.getElementById('dec').addEventListener('click', () => {
count--;
countEl.textContent = count;
});
</script>คำศัพท์: DOM (Document Object Model — "โครงสร้างต้นไม้ของหน้าเว็บ" ที่ browser สร้างจาก HTML แล้ว JS เข้าไปแก้ได้)
ปัญหา:
- DOM manipulation manual (การแก้ DOM ด้วยมือเอง) — ต้อง update textContent เอง
- State (ข้อมูลที่ component เก็บไว้ — จะอธิบายละเอียดใน §5) กับ UI ไม่ตรงกันง่าย (desync) — ถ้าลืม update textContent → UI ผิด
- พอโค้ดใหญ่ขึ้น (scale = รองรับงานขนาดใหญ่ขึ้น) ดูแลลำบาก — UI ใหญ่ ๆ มี state 50 ตัว → ต้อง update 50 ที่
- Element id ชนกัน — ใช้ component ที่มี id ซ้ำกันไม่ได้
1.2 jQuery — ลด pain แต่ไม่หาย
js
$('#inc').click(() => {
let count = parseInt($('#count').text());
$('#count').text(count + 1);
});แค่สั้นลง — ปัญหา DOM manipulation ยังอยู่
1.3 ปัญหา core: UI = function ของ state ไม่ใช่ "list of actions"
อ่านโค้ด vanilla JS — ดู logic ว่า UI เปลี่ยนยังไง ต้องไล่ event handler ทุกตัว ดู side effect ทั่ว ๆ ไป
จริง ๆ แล้ว UI ควรเป็น "function of state":
text
state = { count: 5 }
UI = render(state) → <p>5</p><button>+</button>ถ้า state เปลี่ยน → UI เปลี่ยนตาม (อัตโนมัติ)
2. React — UI as function of state
React บอกว่า: อย่าแก้ DOM เอง — แค่บอกว่า UI ควรเป็นอะไรตาม state — เดี๋ยว React update DOM ให้
👀 โค้ดข้างล่างนี้คือ "หน้าตา" ของ React — ลองอ่านดู ถ้าไม่เข้าใจทุกบรรทัดก็ไม่เป็นไร แค่ดูภาพรวมว่า React เขียนหน้าตาแบบนี้ ทุกบรรทัด (
useState,[count, setCount],{count},onClick={() => ...}) จะอธิบายละเอียดใน §3.3 (destructuring) และบทที่ 1 (JSX + state)
jsx
// import { useState } from 'react'; // ต้อง import ก่อนใช้ (จะเห็นการ import จริงในบท 1)
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>+</button>
<button onClick={() => setCount(count - 1)}>-</button>
</div>
);
}อ่านได้ว่า:
- มี state
countเริ่มที่ 0 - UI =
<div>...{count}...</div> - กดปุ่ม + → setCount(count + 1) → state เปลี่ยน → React re-render (วาด UI ใหม่) → DOM อัพเดทเอง
📘 คำศัพท์ใหม่: declarative vs imperative
- Declarative (เชิงประกาศ) — บอกว่า "อยากได้ผลลัพธ์อะไร" แล้วให้เครื่องมือจัดการเอง → แบบ React
- Imperative (เชิงสั่งการ) — เขียนทีละขั้นว่า "ทำอะไรก่อนหลัง" → แบบ vanilla JS ข้างบน
สรุปสั้น ๆ: declarative บอก "อยากได้อะไร", imperative บอก "ทำยังไง" สองคำนี้จะเจอตลอดทั้งเล่ม
2.1 Component — หน่วยของ UI
React UI = "tree (โครงสร้างแบบต้นไม้) ของ component" — แต่ละ component คือ function ที่ return UI
jsx
// โค้ดนี้เป็นภาพรวมแนวคิดเท่านั้น — component แต่ละตัวนิยามแยกกันในไฟล์จริง (จะเห็นตัวอย่างจริงในบท 1)
function App() {
return (
<div>
<Header />
<Main>
<Counter />
<UserList />
</Main>
<Footer />
</div>
);
}- Reuse (ใช้ซ้ำ) — Counter ใช้ที่ไหนก็ได้
- Isolate (แยกส่วน) — แก้ Counter ไม่กระทบ Footer
- Test (ทดสอบแยกได้) — test component แยกได้
2.2 Virtual DOM — กลไกเบื้องหลัง (under the hood)
ทำไม React ใช้ Virtual DOM:
- React สร้าง "Virtual DOM" — JS object ที่แทน DOM ใน memory
- ตอน state เปลี่ยน — React สร้าง Virtual DOM ใหม่
- Compare กับ Virtual DOM เก่า — หา diff
- อัพเดท DOM จริง เฉพาะส่วนที่ต่าง
💡 Virtual DOM ≠ "เร็วกว่า DOM" — เป็นความเข้าใจผิดที่ React team แก้มาหลายปี (อ้างอิงจากบทความ "React as a UI Runtime" โดย Dan Abramov — สมาชิกทีมหลักผู้พัฒนา React ตัวจริง ไม่ต้องหาอ่านตอนนี้ก็ได้ แค่รู้ว่ามีคนยืนยันเรื่องนี้ไว้แล้ว) VDOM = programming model (รูปแบบการเขียนโปรแกรม) ที่ทำให้ "เขียน UI แบบ declarative (บอกแค่ผลลัพธ์)" ได้ — ไม่ใช่ performance trick ของจริง: เขียน raw DOM update เก่งๆ อาจเร็วกว่า VDOM ได้ในบางกรณี แต่ ดูแลโค้ดไม่ไหวเมื่อ app โต — นี่คือ tradeoff ที่ React ตัดสินใจให้แทน และ React Compiler (ปี 2025-2026) ช่วย optimize เพิ่มเติมได้ VDOM ขายตรงที่ "เขียน declarative ได้, มี abstraction (ชั้นกลางที่ซ่อนรายละเอียด) ดี, ให้ JIT (Just-In-Time = ปรับโค้ดให้เร็วตอนรัน) optimize ได้" — ไม่ใช่ "DOM เร็วกว่า"
💡 เกร็ดเทคนิค (ข้ามได้): React มี engine ภายในชื่อ Fiber — ตอนนี้ยังไม่ต้องรู้ก็เขียน React ได้ ละเอียดในบท 14
⚠️ ข้าม §2.2.5 ในรอบแรก — เนื้อหาด้านล่างเป็น preview ของบท 11 (Next.js) สำหรับคนที่อยากรู้ภาพรวมยุค 2026 เท่านั้น
มือใหม่ที่เพิ่งเริ่ม: กระโดดไป §2.3 ได้เลย แล้วค่อยกลับมาอ่านตอนเรียนบท 11 — โค้ดตัวอย่างในหัวข้อนี้ต้องรันใน Next.js เท่านั้น ถ้าสร้าง project ด้วย Vite (จะทำในบท 1) แล้วลองคัดลอกโค้ดนี้ไปรัน จะเกิด error
2.2.5 RSC — Server Components (preview, ข้ามได้)
RSC = React Server Components — component ที่ render ฝั่ง server (จะอธิบายด้านล่าง)
(RSC ต้องใช้ผ่าน framework ที่รองรับ เช่น Next.js — ไม่ใช่ feature ของ React core ที่ใช้ได้ทุก environment เริ่มใช้กว้างผ่าน App Router — ระบบกำหนดเส้นทาง URL (routing) แบบใหม่ของ Next.js ตั้งแต่ Next 13+ และเป็น default ใน Next 15)
ปี 2026 mental model (แบบจำลองความคิดที่ใช้ทำความเข้าใจเรื่องนี้) ของ React ขยายเป็น 2 ประเภทของ component:
- Server Components (default ใน Next.js App Router) — render ที่ server แล้วส่ง HTML/payload (ข้อมูลที่ส่งกลับมาให้หน้าเว็บ) กลับมาให้ browser
- ไม่มี JS ติดไป client → bundle (ก้อน JS ที่ส่งให้ browser) เล็กลง
- เขียน async ได้ตรงๆ (
async function Page()+await fetch()) - ใช้ DB / file system / env vars (environment variables — ค่าคอนฟิกลับ เช่น API key) ได้เลย
- ไม่มี hooks / state / event handlers
- Client Components (มี
'use client'directive — คำสั่งพิเศษที่เป็น string วางหัวไฟล์ บอก React ว่าไฟล์นี้รันฝั่ง client — ตอนเริ่มไฟล์) — เหมือน React เดิม มี hooks/state/onClick
typescript
// ── ไฟล์ที่ 1: PostList.tsx (Server Component, default ใน Next 15) ──
// ⚠️ โค้ดนี้รันได้เฉพาะใน Next.js project — ลองใน React ปกติจะ error
async function PostList() {
const posts = await db.posts.findMany();
return (
<ul>
{posts.map(p => <li key={p.id}>{p.title}</li>)}
</ul>
);
// React escape JSX text expression ให้อัตโนมัติ — ปลอดภัยจาก XSS ใน JSX text node
}
// ── ไฟล์ที่ 2: LikeButton.tsx (Client Component, มี interactivity) ──
// 'use client' ต้องอยู่บรรทัดแรกสุดของไฟล์ (top-of-file directive) เท่านั้น
// วางไว้ที่อื่นจะไม่มีผล — Next.js จะไม่รับรู้ว่าเป็น Client Component
'use client';
import { useState } from 'react';
function LikeButton() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}(เล่มนี้สอน Vite (CSR-first) ใน บท 1-10 → ไปต่อ Next.js + Server Components ในบท 11)
2.3 React ≠ framework — เป็น "library"
React โฟกัสที่ UI เท่านั้น — เรื่องอื่นต้องเลือก library เอง:
💡 ยังไม่ต้องรู้ทุกตัวตอนนี้ — แค่รู้ว่า React เลือกได้หลาย library ตามงาน
| งาน | choices |
|---|---|
| Routing (จัดการเส้นทาง URL) | React Router, TanStack Router |
| Data fetching (ดึงข้อมูลจาก server) | TanStack Query, SWR |
| Global state (state ที่ใช้ร่วมกันทั้งแอป) | Zustand, Redux Toolkit, Jotai |
| Form (จัดการ form + validation) | React Hook Form |
| UI library (ชุด component สำเร็จรูป) | shadcn/ui, MUI, Chakra |
| Build tool (รวม+แปลงโค้ดให้ browser รัน) | Vite (default), Next.js (full-stack), React Router v7 / framework mode (เดิมคือ Remix) |
มี freedom (อิสระเลือกเอง) + fatigue (เหนื่อยล้าจากตัวเลือกเยอะ — ศัพท์ฮิตในวง JS เรียก JavaScript fatigue) — ต้องเลือกเอง
3. JS Modern Essentials — ที่ต้องรู้ก่อนเขียน React
3.1 let / const (ไม่ใช่ var)
js
let count = 0; // เปลี่ยนค่าได้
const name = "Anna"; // เปลี่ยนค่าไม่ได้ (reassign ไม่ได้)const ใช้เป็น default — เปลี่ยนเป็น let เมื่อจำเป็น
3.2 Arrow function
js
// 👇 แต่ละบล็อกเป็นตัวอย่าง "แยกกัน" — อย่า copy ทั้งก้อนไปรันรวม
// (เพราะใช้ชื่อต่างกันคนละบล็อก ป้องกัน "Identifier already declared")
// แบบเก่า (function ปกติ)
function add(a, b) {
return a + b;
}
// แบบ arrow (ลูกศร) — สั้นกว่า
const addArrow = (a, b) => a + b;
// หลายบรรทัด — ต้องมี {} ครอบ แล้ว return เอง
const addArrowBlock = (a, b) => {
const result = a + b;
return result;
};ใช้บ่อยมากใน React — โดยเฉพาะใน callback:
jsx
<button onClick={() => setCount(count + 1)}>+</button>3.3 Destructuring
js
// Array — ดึงค่าตามตำแหน่ง
const [first, second] = [1, 2, 3];
// first=1, second=2
// Object — ดึงค่าตามชื่อ key
const user = { name: "Anna", age: 25 };
const { name, age } = user;
// name="Anna", age=25
// rename — เปลี่ยนชื่อตัวแปรตอนดึง
const { name: userName } = user;
// userName="Anna"
// default value — ค่าตั้งต้นถ้าไม่มี key นั้น
const { name = "Unknown" } = {};ใน React เจอบ่อยใน props:
jsx
function Greeting({ name, age }) { // แตก (destructure) props ออกมาใช้ตรง ๆ
return <p>{name}, {age}</p>;
}3.4 Spread / Rest
js
// spread (...) — กระจายของในกล่องออกมา
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]
const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 }; // { a: 1, b: 2, c: 3 }
// rest (...) — รวบของหลายตัวเข้ามาในที่เดียว
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}
// 👇 snippet แยกจาก §3.3 — ถ้า copy ทั้งบทมารันรวม ให้เปลี่ยนชื่อ first
const [head, ...rest] = [1, 2, 3, 4];
// head=1, rest=[2,3,4]ใน React ใช้ update state แบบ immutable:
js
setUser({ ...user, age: user.age + 1 });3.5 Template literal
js
const name = "Anna";
const message = `Hello, ${name}!`; // backtickหลายบรรทัด:
js
const html = `
<div>
<p>${name}</p>
</div>
`;3.6 Array methods
js
const numbers = [1, 2, 3, 4, 5];
// map — แปลงทุกตัว ได้ array ใหม่ขนาดเท่าเดิม
numbers.map(n => n * 2); // [2, 4, 6, 8, 10]
// filter — กรองเอาเฉพาะตัวที่เงื่อนไขเป็นจริง
numbers.filter(n => n > 2); // [3, 4, 5]
// reduce — ยุบทุกตัวให้เหลือค่าเดียว (acc = ตัวสะสม)
numbers.reduce((acc, n) => acc + n, 0); // 15
// find — หาตัวแรกที่ตรงเงื่อนไข
numbers.find(n => n > 3); // 4
// some = มีบางตัวที่จริงไหม / every = ทุกตัวจริงไหม
numbers.some(n => n > 4); // true
numbers.every(n => n > 0); // trueใน React ใช้ map render list:
jsx
{users.map(user => <UserCard key={user.id} user={user} />)}3.7 async / await
js
// แบบ Promise เดิม (ต่อ .then ทีละสเต็ป)
fetch('/api/users')
.then(res => res.json())
.then(data => console.log(data));
// แบบ async/await — อ่านง่ายเหมือนโค้ดธรรมดา (await = รอให้เสร็จก่อน)
async function loadUsers() {
const res = await fetch('/api/users');
const data = await res.json();
console.log(data);
}3.8 Optional chaining ?.
js
const city = user?.address?.city;
// ถ้า user หรือ address เป็น null → ได้ undefined แทน error3.9 Nullish coalescing ??
js
const name = user.name ?? "Unknown";
// ถ้า user.name เป็น null/undefined → "Unknown"
// ต่างจาก || ที่จะ replace ค่า falsy ทุกแบบ (0, "", false)3.10 Numeric separator _ — ขีดล่างในตัวเลข (หัวข้อเล็ก ข้ามได้ก่อน)
ไม่ใช่ของสำคัญเท่าหัวข้ออื่นในบทนี้ — แค่เจอบ่อยพอจะรู้ไว้ ข้ามไปอ่านทีหลังก็ได้
เลขยาว ๆ อ่านยาก เลยใส่ _ คั่นได้ (JS มองข้าม _ ตอนคำนวณ):
js
const million = 1_000_000; // = 1000000 (อ่านง่ายขึ้น เครื่องอ่านเป็น 1000000 เหมือนเดิม)
const oneMinute = 60_000; // = 60000 มิลลิวินาทีเจอบ่อยในบทหลัง ๆ เช่น
const delay = 60_000 // รอ 60 วินาที (60,000 มิลลิวินาที)—_แค่ช่วยให้คนอ่านง่าย ไม่มีผลต่อค่า
3.11 Modules
js
// math.js
export function add(a, b) { return a + b; }
export const PI = 3.14;
export default function multiply(a, b) { return a * b; }
// main.js
import multiply, { add, PI } from './math.js';ใน React: ทุก component เป็น module — export/import กันไปมา
4. TypeScript — พื้นฐาน
💡 ไม่เคย TS เลย? อ่านแค่ §4.1-§4.5 พอ — §4.6 Generics เป็นของขั้นสูง เจอครั้งจริงในบท 13 ตอนเริ่มเขียน React ใหม่ใช้ JS เปล่าๆ ก่อนก็ได้ (Vite รองรับ) แต่ template default ของ React สมัยใหม่ + library ส่วนใหญ่ใช้ TS
TypeScript คือ JavaScript ที่มีระบบตรวจสอบชนิดข้อมูล (type) — เขียนคล้าย JavaScript แต่เพิ่ม syntax พิเศษเพื่อช่วยจับ bug ตั้งแต่ก่อนรัน
React ปัจจุบันใช้ TypeScript เป็น default
4.1 ทำไมต้อง TS
JavaScript เป็น dynamic typing (กำหนดชนิดข้อมูลตอนรัน ไม่ใช่ตอนเขียนโค้ด) — bug เจอตอน run:
js
function greet(user) {
return "Hello, " + user.name.toUpperCase();
}
greet({ user: "Anna" }); // 💥 user.name undefined → toUpperCase crashTypeScript เพิ่ม type → จับตอน compile:
ts
function greet(user: { name: string }) {
return "Hello, " + user.name.toUpperCase();
}
greet({ user: "Anna" }); // ❌ compile error: missing 'name' (field name หายไป → TS แจ้ง error ก่อนรัน)4.2 Basic types
ts
let count: number = 0;
let name: string = "Anna";
let isActive: boolean = true;
let items: string[] = ["a", "b"]; // array
let pair: [number, string] = [1, "a"]; // tuple
let nothing: null = null;
let undef: undefined = undefined;
let anything: any = "x"; // ปิดระบบ type — ไม่ปลอดภัย ควรหลีกเลี่ยง (ใช้ unknown แทน)
let unknown: unknown = "x"; // แบบ any ที่ยังต้อง check ชนิดก่อนใช้ (type-safe = ปลอดภัยเรื่อง type)4.3 Interface / Type
ts
// 👇 option A — ใช้ interface
interface User {
id: string;
name: string;
age: number;
email?: string; // optional
readonly createdAt: Date;
}
const u: User = { id: "1", name: "Anna", age: 25, createdAt: new Date() };ts
// 👇 option B — ใช้ type (เลือกใช้ตัวใดตัวหนึ่ง อย่าประกาศคู่กันในไฟล์เดียว)
// ⚠️ สองบล็อกนี้เป็น option แยกกัน — อย่าคัดลอกทั้ง 2 blocks ลงในไฟล์เดียวกัน (จะเกิด duplicate identifier error)
type User = {
id: string;
name: string;
age: number;
};
interfacevstype— ใช้แทนกันได้ในกรณีส่วนใหญ่ ความต่าง:
interface— extend ได้ (declaration merging = ประกาศชื่อเดิมซ้ำได้ TS รวมให้เอง) เหมาะกับ public API (ส่วนที่เปิดให้คนอื่นใช้ เช่น library)type— ทำ union / intersection / mapped types ได้คล่องกว่า เหมาะกับ data shape (รูปข้อมูล) ภายในแอปในทีมส่วนใหญ่ขอแค่ "เลือกแล้วใช้ตัวเดียวกันทั้งโปรเจกต์" (team convention = ข้อตกลงในทีม — รายละเอียดในบท 13 เช็ค TypeScript handbook official ก่อนตั้ง)
4.4 Union + Literal
ts
type Status = "loading" | "success" | "error";
let status: Status = "loading";
status = "done"; // ❌ error
type ID = number | string;
let id: ID = 123;
id = "abc";4.5 Function
ts
// 👇 สองบล็อกข้างล่างเป็นตัวอย่าง "แยกกัน" — อย่า copy ทั้งก้อนไปรันรวม
// (ใช้ชื่อเดียวกันคนละสไตล์ ป้องกัน "Cannot redeclare block-scoped variable")
// แบบ function ปกติ
function add(a: number, b: number): number {
return a + b;
}
// แบบ arrow (snippet แยก)
const addArrow = (a: number, b: number): number => a + b;
// optional + default param
function greet(name: string, greeting: string = "Hello"): string {
return `${greeting}, ${name}`;
}4.6 Generics
ts
function first<T>(arr: T[]): T | undefined {
return arr[0];
}
first([1, 2, 3]); // T = number → return number
first(["a", "b"]); // T = string → return string4.7 ใน React
ตัวอย่าง component พร้อม TS:
tsx
type ButtonProps = {
label: string;
onClick: () => void;
disabled?: boolean;
};
// `disabled = false` คือค่า default — ถ้า parent ไม่ส่ง prop `disabled` มา จะใช้ false
function Button({ label, onClick, disabled = false }: ButtonProps) {
return (
<button onClick={onClick} disabled={disabled}>
{label}
</button>
);
}
// ใช้
<Button label="Save" onClick={() => console.log("clicked")} />💡 ในหนังสือนี้เราจะใช้ TypeScript เป็นหลัก — เริ่มต้นยากกว่านิด แต่จะคุ้มในระยะยาว
5. คำศัพท์ที่ต้องรู้
💡 คำบางคำในตารางนี้จะเห็นในบทถัดไป — ดูตารางนี้เป็น reference ได้ภายหลัง ตอนนี้แค่อ่านผ่านพอ
| คำ | ความหมาย |
|---|---|
| JSX | syntax คล้าย HTML ที่เขียนใน JS — React ใช้ |
| TSX | JSX + TypeScript |
| Component | function ที่ return JSX — หน่วยของ UI |
| Props | "argument" ของ component (read-only) |
| State | data ที่ component เก็บ + เปลี่ยนได้ |
| Hook | function พิเศษ (useState, useEffect) ที่ใช้ใน component |
| Render | กระบวนการ React สร้าง UI |
| Re-render | render ใหม่เมื่อ state/props เปลี่ยน |
| Virtual DOM | object แทน DOM ใน memory ที่ React ใช้ diff |
| Reconciliation | กระบวนการ diff (เปรียบเทียบหาความต่าง) Virtual DOM แล้ว update DOM จริง |
| Lift state up | ยก state ขึ้นไปไว้ที่ parent เพื่อให้ลูก ๆ ใช้ร่วมกันได้ (เจอครั้งแรกในบท 1 §9) |
| Controlled component | form input ที่ React ควบคุม value |
| Side effect | งานที่ไม่ใช่ render เช่น fetch data, set timer |
6. ภาพรวมเครื่องมือยุค 2026
| Tool | คือ |
|---|---|
| Vite 6+ | build tool (เครื่องมือแปลง+รวมโค้ดให้ browser รัน) — default ปัจจุบัน · เร็วกว่า Webpack (bundler รุ่นเก่า) และ CRA มาก • CRA = Create React App = เครื่องมือเก่าที่เคยใช้สร้าง React project ก่อนมี Vite • CRA ถูก deprecated (ยกเลิกใช้อย่างเป็นทางการ) โดยทีม React ก.พ. 2025 — ห้ามใช้ในโปรเจกต์ใหม่ (อ้างอิง: react.dev/blog/2025/02/14/sunsetting-create-react-app) • Vite 6+ มี rolldown-vite เป็น opt-in (เลือกเปิดเอง ไม่ใช่ default — จะกลายเป็น default ในอนาคต) · อ้างอิง vite.dev สำหรับ version ล่าสุด |
| Next.js 15 | framework full-stack ที่ครอบ React (รองรับงานทั้งหน้าบ้าน-หลังบ้าน) — มี SSR, App Router, Server Actions, PPR (Partial Prerendering = render หน้าบางส่วนล่วงหน้า, ไว้เจอบท 11) |
| TypeScript 5+ | superset (ส่วนขยาย) ของ JS — เพิ่มระบบ type |
| Biome | เครื่องมือ lint (ตรวจโค้ด) + format (จัดรูปแบบโค้ด) รวมในตัวเดียว (แทน ESLint + Prettier) — โฆษณาตัวเองว่าเร็วกว่ามาก เพราะเขียนด้วย Rust (ตัวเลข "X เท่า" ขึ้นกับ benchmark/config — เช็ค biomejs.dev ก่อนอ้างใน PR, flagged 2026-06) |
| ESLint + Prettier | ทางเลือกเดิม — ยังใช้กันแพร่หลาย |
| React DevTools | ส่วนเสริม (extension) ของ browser ไว้ debug React |
| shadcn/ui | ชุด component สำเร็จรูปยุค 2024-2026 (copy โค้ดมาวางเอง ไม่ได้ install เป็น package) |
| TanStack Query v5 | library ดึง (fetch) + จำ (cache) ข้อมูลจาก server (บท 4) |
| Tailwind CSS v4 | CSS แบบ utility-first (จัดสไตล์ด้วย class สำเร็จ) — เครื่องยนต์ชื่อ Oxide, ตั้งค่าจากไฟล์ CSS โดยตรง |
| Bun | runtime + package manager ทางเลือก — เคลมความเร็วสูงกว่า npm ในงาน install/run script (ตัวเลข "X เท่า" ขึ้นกับ scenario — เช็ค bun.sh benchmark ปัจจุบันก่อนอ้าง, flagged 2026-06) |
| React Compiler | plugin (ส่วนเสริม) ที่เสียบเข้ากับ Babel หรือ SWC (= เครื่องมือแปลง JS modern ให้ browser รุ่นเก่าเข้าใจได้ — Babel เขียนด้วย JS, SWC เขียนด้วย Rust เร็วกว่า) ทำ auto memoization (จำผลลัพธ์อัตโนมัติเพื่อไม่ต้องคำนวณซ้ำ ลด re-render) — RC (Release Candidate = รุ่นเกือบสมบูรณ์) ปี 2025 ยังต้อง opt-in (ต้องเปิดใช้เอง) ผ่าน babel-plugin-react-compiler แยก (ไม่ bundle ใน React 19 core) · Next.js 15+ มี opt-in flag ใน next.config · (ไว้เจอบท 14) |
ตอนแรกใช้แค่ Vite + React + TypeScript เพียงพอ — ตัวที่เหลือค่อย ๆ รู้จักในบทหลัง
7. Checkpoint ความเข้าใจ
🛠️ Checkpoint 0.1 — JS ทบทวน
แปลงโค้ดต่อไปนี้เป็น modern JS:
js
function getNames(users) {
var names = [];
for (var i = 0; i < users.length; i++) {
if (users[i].active) {
names.push(users[i].name);
}
}
return names;
}📖 เฉลย
js
const getNames = (users) => users.filter(u => u.active).map(u => u.name);หรือพร้อม TS:
ts
type User = { name: string; active: boolean };
const getNames = (users: User[]): string[] =>
users.filter(u => u.active).map(u => u.name);🛠️ Checkpoint 0.2 — React mental model
💡 Checkpoint นี้ตอบในหัวหรือเขียนบนกระดาษก็ได้ — ยังไม่ต้องรัน code จริง ให้กลับมาตรวจคำตอบหลังจากทำบท 1 แล้ว
อ่านโค้ดนี้แล้วบอก: state เปลี่ยน → React ทำอะไร
jsx
function App() {
const [text, setText] = useState("");
return (
<div>
<input value={text} onChange={e => setText(e.target.value)} />
<p>You typed: {text}</p>
</div>
);
}📖 เฉลย
- ผู้ใช้พิมพ์ใน input → trigger
onChange setText(newValue)→ React อัปเดต state เป็นค่าใหม่- React run
App()ใหม่ → return JSX ใหม่ - Diff กับ JSX เก่า → เห็นว่า text เปลี่ยน
- Update DOM จริง — แค่
<p>เท่านั้น (input ไม่ต้อง update เพราะ value มาจาก state แล้ว)
ทั้งหมดเกิดในไม่กี่ ms — เหมือนทันที
8. สรุปบท
✅ Vanilla JS = ต้อง manipulate DOM เอง + sync state ↔ UI ยาก ✅ React = UI as function of state — declarative ✅ Virtual DOM + diff = update DOM จริงแค่ส่วนที่ต่าง — เร็ว ✅ Component-based — reuse + isolate + test ง่าย ✅ JS modern ที่ใช้บ่อย: arrow, destructuring, spread, map/filter, async/await ✅ TypeScript ช่วยจับ bug ก่อน run — ปี 2026 ใช้กับ React default ✅ Tool: Vite + TypeScript + React = stack เริ่มต้นที่ดี ✅ React 19 features ใหม่ — ข้ามได้ทั้งหมด นี่คือ preview เฉยๆ ยังไม่ต้องเข้าใจตอนนี้ แค่รู้ว่ามีอยู่ — จะเจอรายละเอียดจริงในบทหลัง:
Actions— จัดการ form ที่ส่งไป serveruseOptimistic— อัพเดท UI ก่อน server ตอบuseActionState— จัดการ state ของ action (แทนuseFormStateที่ถูก deprecated ใน React 19)useFormStatus— ดูสถานะ form ที่กำลัง submituse()— อ่าน Promise หรือ Context ใน render function ได้โดยตรงReact Compiler— optimize auto memoization อัตโนมัติ (ไม่ต้องเขียน useMemo/useCallback เอง) ✅ TS features ที่ควรรู้เพิ่ม (ไว้เจอละเอียดบท 13):as const,satisfies, discriminated union (union ที่แยกแยะได้ด้วย field พิเศษ), polymorphic component (component ที่เปลี่ยน tag html ได้)
🔤 Glossary · 📋 Style guide · 📅 last_verified: 2026-06-12