ข้ามไปยังเนื้อหา

$derived — Computed Values

useMemo ของ React จดจำผลการคำนวณที่หนัก — แต่คุณต้องประกาศ reactive input ทุกตัวใน dependency array มิฉะนั้นค่าจะเก่า Svelte 5’s $derived ทำสิ่งเดียวกันโดยไม่ต้องใช้ array: คอมไพเลอร์สแกน expression หาตัวแปร reactive ทุกตัวที่อ่าน และรันการคำนวณใหม่อัตโนมัติเมื่อใดก็ตามที่ค่าเหล่านั้นเปลี่ยน

React
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>
);
}
Svelte
<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(expr) รับได้แค่ expression เดียว เมื่อการคำนวณต้องใช้หลาย statement — filter, reduce หรือ conditional — ใช้ $derived.by(() => { ... return result; }) แทน ซึ่งตรงกับ useMemo ที่มี function body หลายบรรทัด

React
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>
);
}
Svelte
<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>
มี $state price และ $state qty จะประกาศ derived total ใน Svelte 5 ยังไง?
ควรใช้ $derived.by แทน $derived เมื่อไหร่?
$derived อ่านจาก $state สองตัวคือ A และ B เมื่ออัปเดต A จะเกิดอะไร?