Reactivity & Lifecycle (Runes)
React จัดระเบียบ reactivity ด้วย hook แต่ละตัวที่แยกกัน เช่น useState, useMemo, useEffect, useRef และอื่น ๆ Svelte 5 แทนที่ทั้งหมดด้วย primitive เดียวที่เรียกว่า runes — คีย์เวิร์ดที่คอมไพเลอร์เข้าใจ โดยขึ้นต้นด้วย $ คุณไม่ได้เรียกใช้สิ่งเหล่านี้เหมือนฟังก์ชันทั่วไป — คอมไพเลอร์จะอ่านโค้ดในขั้นตอน build และสร้างโค้ด reactive ที่ถูกปรับแต่งให้มีประสิทธิภาพสูงให้คุณ
โมดูลนี้คือ แกนกลางของหลักสูตร บทเรียนถัดไปแต่ละบทจะลงลึกในแต่ละ rune โดยเฉพาะ เริ่มต้นที่นี่เพื่อให้ได้ mental map ครบก่อนดำน้ำลึก
ตารางเปรียบเทียบ runes ↔ hooks
หัวข้อที่มีชื่อว่า “ตารางเปรียบเทียบ runes ↔ hooks”| React hook | Svelte 5 rune | หน้าที่ |
|---|---|---|
useState(init) | $state(init) | ค่า reactive — แก้ไขตรงได้เลย ไม่ต้องใช้ setter |
useMemo(() => expr, deps) | $derived(expr) | ค่าที่คำนวณ — ติดตาม dependencies อัตโนมัติ ไม่ต้องระบุ deps array |
useMemo(() => fn(), deps) | $derived.by(() => fn()) | ค่าที่คำนวณพร้อม function body หลายบรรทัด |
useEffect(fn, deps) | $effect(fn) | Side-effect — ติดตาม dependencies อัตโนมัติ |
useEffect(fn, []) | onMount(fn) | รันครั้งเดียวหลัง component mount |
useEffect(() => () => cleanup, []) | onDestroy(fn) | รันครั้งเดียวเมื่อ component ถูกทำลาย |
useRef(init) | ตัวแปร let ธรรมดา หรือ bind:this | ref ที่เปลี่ยนได้โดยไม่ทำให้ re-render |
useContext(Ctx) | getContext(key) | อ่าน context จาก ancestor |
| Component props | $props() | ประกาศและ destructure props ที่รับเข้ามา |
| Callback props / lifting state | $bindable() | prop ที่ bind แบบสองทาง |
การเปลี่ยนแปลงเชิงแนวคิดที่ใหญ่ที่สุด: React hooks ต้องการ dependency array ที่ระบุชัดเจน runes ของ Svelte ถูก track โดยคอมไพเลอร์ — คุณไม่ต้องระบุ dependency ด้วยตนเองเลย
Counter แรกที่รันได้จริง
หัวข้อที่มีชื่อว่า “Counter แรกที่รันได้จริง”function Counter() { const [count, setCount] = React.useState(0); const doubled = React.useMemo(() => count * 2, [count]);
React.useEffect(() => { document.title = 'Count: ' + count; }, [count]);
return ( <div> <button onClick={() => setCount(c => c + 1)}>+1</button> <p>Count: {count} — Doubled: {doubled}</p> </div> );}<script> let count = $state(0); let doubled = $derived(count * 2);
$effect(() => { document.title = 'Count: ' + count; });</script>
<button onclick={() => count++}>+1</button><p>Count: {count} — Doubled: {doubled}</p>สาม runes ไม่มี dependency array เลยแม้แต่ครั้งเดียว คอมไพเลอร์รู้เองว่า doubled ขึ้นกับ count และ $effect ควรรันใหม่ทุกครั้งที่ count เปลี่ยน