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

The Context API

เมื่อ component ที่ nested หลายตัวต้องการข้อมูลเดียวกัน — theme, user ปัจจุบัน, shared state ของ form — การส่งผ่านทุก component กลางในฐานะ props (prop drilling) น่ารำคาญและรก context ให้ ancestor set ค่าที่ descendant ไหนก็อ่านได้โดยตรง

  • setContext(key, value) — เรียกใน component ตอน initialization; ทำให้ value ใช้ได้กับ descendant ทุกตัวภายใต้ key
  • getContext(key) — เรียกใน descendant ไหนก็ได้; อ่านค่าของ ancestor ที่ใกล้ที่สุดสำหรับ key
Parent.svelte
<script>
import { setContext } from 'svelte';
setContext('theme', 'dark');
</script>
<slot-like-children />
<!-- DeepChild.svelte (ลึกแค่ไหนก็ได้) -->
<script>
import { getContext } from 'svelte';
const theme = getContext('theme'); // 'dark' — ไม่ต้อง thread props ผ่านมา
</script>
<div class={theme}></div>
flowchart TB
  parent["Ancestor: setContext theme value"] --> mid["component กลาง
(ไม่ต้องใช้ props)"]
  mid --> child["Descendant: getContext theme"]
context ไหลลงไปหา descendant ทุกตัว

setContext run ครั้งเดียวตอน init — ค่า ที่เก็บไม่ reactive ในตัวเอง ถ้าจะแชร์ข้อมูลที่ reactive ให้ใส่ runed object เข้า context แล้วอ่าน property ของตัวเองใน descendant; เพราะ $state object เป็น deeply reactive การเปลี่ยนแปลงจึงกระจายไป

<!-- เก็บ runed object ไม่ใช่ plain snapshot -->
<script>
import { setContext } from 'svelte';
let cart = $state({ items: [] });
setContext('cart', cart); // descendant เห็น update ของ cart.items แบบ live
</script>

pattern ที่พบบ่อยคือ factory เล็ก ๆ ที่สร้าง runed state และจับคู่ setContext/getContext ไว้หลัง helper function ที่มี type เพื่อให้ผู้ใช้แค่เรียก getCart()

  • Props — ดีที่สุดสำหรับข้อมูล parent→child ตรง ๆ ชัดเจนและ trace ง่าย
  • Context — ดีที่สุดเมื่อข้อมูลต้องใช้โดย descendant หลายตัว ในความลึกต่างกัน (theme, auth, shared state ของ widget) และ scope อยู่ใน subtree
  • Module state (.svelte.js) — ดีที่สุดสำหรับ state ที่ global จริง ๆ แต่ต้องระวัง SSR (module singleton ถูกแชร์ข้าม request บน server — โมดูล state-management อธิบายเรื่องนี้)

สิ่งสำคัญคือ context เป็น ต่อ component tree และต่อ render ดังนั้นบน server แต่ละ request จึงได้ context ของตัวเอง — ทำให้ context เป็นวิธีแชร์ state ระดับ request แบบ SSR-safe ไม่เหมือน module-level singleton

context แก้ปัญหาอะไร?
แชร์ข้อมูลที่ reactive ผ่าน context ยังไง?
ทำไม context ถึงปลอดภัยกว่า module-level singleton สำหรับ state ระดับ request บน server?
ควรเลือก props เหนือ context เมื่อไร?