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

Lifecycle — onMount, onDestroy, tick

React ใช้ useEffect เดียวสำหรับทุกอย่าง: mount, update และ cleanup Svelte 5 แยกความรับผิดชอบชัดเจนกว่า $effect จัดการ reactive updates (ครอบคลุมในบทเรียนก่อนหน้า) onMount และ onDestroy จัดการ setup และ teardown ที่รันครั้งเดียว tick เป็น utility สำหรับ flush pending DOM updates ก่อนอ่าน layout

ReactSvelte 5หมายเหตุ
useState(init)$state(init)Mutate ตรงได้เลย ไม่มี setter
useMemo(() => expr, deps)$derived(expr)ไม่มี deps array — compiler track
useMemo(() => fn(), deps)$derived.by(() => fn())Multi-statement derived
useEffect(fn, deps)$effect(fn)ไม่มี deps array — auto-tracked
useEffect(fn, [])onMount(fn)รันครั้งเดียวหลัง mount
useEffect(() => cleanup, [])onDestroy(fn)รันครั้งเดียวเมื่อ destroy
useRef(init)let variablelet ธรรมดาสำหรับ mutable non-reactive ref
useRef(null) + ref={el}bind:this={el}DOM element reference
useContext(Ctx)getContext(key)อ่านจาก ancestor provider ที่ใกล้ที่สุด
createContext() + ProvidersetContext(key, value)Provide context
Component props$props()Destructure พร้อม defaults
Callback props (lifting state)$bindable() + bind:Two-way โดยไม่มี explicit callback
React
function Clock() {
const [time, setTime] = React.useState(new Date());
React.useEffect(() => {
const id = setInterval(() => setTime(new Date()), 1000);
return () => clearInterval(id);
}, []);
return <p>{time.toLocaleTimeString()}</p>;
}
Svelte
<script>
import { onMount } from 'svelte';
let time = $state(new Date());
onMount(() => {
const id = setInterval(() => { time = new Date(); }, 1000);
return () => clearInterval(id);
});
</script>
<p>{time.toLocaleTimeString()}</p>

onMount รับ setup function และ optional return cleanup function ซึ่งรันเมื่อ destroy — semantics เดียวกับ useEffect(fn, []) ทุกอย่าง

React
function Analytics() {
React.useEffect(() => {
trackPageView('/dashboard');
return () => {
trackPageLeave('/dashboard');
};
}, []);
return <div>Dashboard</div>;
}
Svelte
<script>
import { onMount, onDestroy } from 'svelte';
onMount(() => trackPageView('/dashboard'));
onDestroy(() => trackPageLeave('/dashboard'));
</script>
<div>Dashboard</div>

การแยก mount และ destroy เป็นสอง call อ่านง่ายกว่าเมื่อ setup และ teardown ไม่เกี่ยวข้องกัน

tick() คืน promise ที่ resolve หลัง Svelte อัปเดต DOM เสร็จ ใช้เมื่อต้องอ่าน layout (เช่น ขนาด element, focus) ทันทีหลัง reactive change — เทียบเท่ากับ await flushSync + requestAnimationFrame ใน React

React
function AutoScroll() {
const ref = React.useRef(null);
const [items, setItems] = React.useState(['a', 'b', 'c']);
function addItem() {
setItems(prev => [...prev, String.fromCharCode(97 + prev.length)]);
// Must use useEffect to scroll after render
}
React.useEffect(() => {
ref.current?.scrollIntoView({ block: 'end' });
}, [items]);
return (
<ul>
{items.map(i => <li key={i}>{i}</li>)}
<li ref={ref} />
</ul>
);
}
Svelte
<script>
import { tick } from 'svelte';
let items = $state(['a', 'b', 'c']);
let endEl;
async function addItem() {
items.push(String.fromCharCode(97 + items.length));
await tick();
endEl?.scrollIntoView({ block: 'end' });
}
</script>
<ul>
{#each items as item}
<li>{item}</li>
{/each}
<li bind:this={endEl}></li>
</ul>
<button onclick={addItem}>Add</button>
อะไรคือ Svelte 5 ที่เทียบเท่า useEffect(fn, []) — รันครั้งเดียวหลัง mount?
ต้องการ reference ไปยัง DOM element ใน Svelte 5 ใช้อะไร?
tick() มีประโยชน์เมื่อไหร่?
อะไรคือ Svelte 5 ที่เทียบเท่า useContext(MyContext)?