$derived — Computed Values
useMemo ของ React จดจำผลการคำนวณที่หนัก — แต่คุณต้องประกาศ reactive input ทุกตัวใน dependency array มิฉะนั้นค่าจะเก่า Svelte 5’s $derived ทำสิ่งเดียวกันโดยไม่ต้องใช้ array: คอมไพเลอร์สแกน expression หาตัวแปร reactive ทุกตัวที่อ่าน และรันการคำนวณใหม่อัตโนมัติเมื่อใดก็ตามที่ค่าเหล่านั้นเปลี่ยน
$derived vs useMemo
หัวข้อที่มีชื่อว่า “$derived vs useMemo”function PriceCalc() { const [price, setPrice] = React.useState(100); const [qty, setQty] = React.useState(3);
const total = React.useMemo(() => price * qty, [price, qty]); const withTax = React.useMemo(() => total * 1.07, [total]);
return ( <div> <p>Unit price: {price} — Qty: {qty}</p> <p>Total: {total} — With tax: {withTax.toFixed(2)}</p> <button onClick={() => setQty(q => q + 1)}>+qty</button> </div> );}<script> let price = $state(100); let qty = $state(3);
let total = $derived(price * qty); let withTax = $derived(total * 1.07);</script>
<p>Unit price: {price} — Qty: {qty}</p><p>Total: {total} — With tax: {withTax.toFixed(2)}</p><button onclick={() => qty++}>+qty</button>ไม่มี [price, qty] dependency array $derived ต่อกันได้ — withTax อ่าน total ซึ่งอ่าน price และ qty คอมไพเลอร์สร้าง reactive graph ทั้งหมดอัตโนมัติ
$derived.by — การคำนวณหลายขั้นตอน
หัวข้อที่มีชื่อว่า “$derived.by — การคำนวณหลายขั้นตอน”$derived(expr) รับได้แค่ expression เดียว เมื่อการคำนวณต้องใช้หลาย statement — filter, reduce หรือ conditional — ใช้ $derived.by(() => { ... return result; }) แทน ซึ่งตรงกับ useMemo ที่มี function body หลายบรรทัด
function FilteredList() { const [items] = React.useState(['apple', 'banana', 'apricot', 'blueberry', 'avocado']); const [query, setQuery] = React.useState('a');
const filtered = React.useMemo(() => { const lower = query.toLowerCase(); return items.filter(item => item.startsWith(lower)); }, [items, query]);
return ( <div> <input value={query} onChange={e => setQuery(e.target.value)} /> <ul>{filtered.map(f => <li key={f}>{f}</li>)}</ul> </div> );}<script> let items = $state(['apple', 'banana', 'apricot', 'blueberry', 'avocado']); let query = $state('a');
let filtered = $derived.by(() => { const lower = query.toLowerCase(); return items.filter(item => item.startsWith(lower)); });</script>
<input bind:value={query} /><ul> {#each filtered as f} <li>{f}</li> {/each}</ul>