Memoization & the Compiler
ปัญหาที่ memoization แก้
หัวข้อที่มีชื่อว่า “ปัญหาที่ memoization แก้”ทุก render จะรัน component ใหม่ ซึ่งสร้าง value ทุกตัวข้างในใหม่หมด — รวมถึง object, array และ function พวกนี้เป็น reference ใหม่ทุกครั้ง แม้เนื้อหาจะเหมือนเดิม ปกติแล้วไม่เป็นไร แต่เป็นปัญหาใน 2 กรณี:
- การคำนวณที่แพง รันทุก render ทั้งที่ input ไม่เปลี่ยน
- reference ใหม่ (function หรือ object) ที่ส่งให้ memoized child ทำลาย memoization ของ child ทำให้ re-render โดยไม่จำเป็น
tool memoization สามตัวจัดการคนละส่วน:
| Tool | cache | ใช้เมื่อ |
|---|---|---|
useMemo(fn, deps) | value (ผลของ fn) | การคำนวณแพง หรือต้องการ object/array reference ที่ stable |
useCallback(fn, deps) | function (reference ที่ stable) | ส่ง callback ให้ memoized child (คือ useMemo สำหรับ function) |
React.memo(Component) | render ของ component | component re-render ด้วย props เดิมและการ render นั้น costly |
// Expensive calc, cached until inputs change:const visibleTodos = useMemo(() => getFilteredTodos(todos, filter), [todos, filter]);
// Stable function reference so a memoized child does not re-render:const handleSelect = useCallback((id) => setSelected(id), []);
// Skip re-render when props are shallowly equal:const Row = React.memo(function Row({ item }) { /* ... */ });เมื่อ memoization ช่วย — และเมื่อกลับทำร้าย
หัวข้อที่มีชื่อว่า “เมื่อ memoization ช่วย — และเมื่อกลับทำร้าย”memoization ไม่ฟรี: เสีย memory และเสียการเทียบทุก render ใส่ไว้ทุกที่ “เผื่อไว้” ทำให้ code รกและอาจติดลบสุทธิ memoization ช่วยจริงเมื่อ:
- การคำนวณที่ cache นั้นแพงแบบวัดได้ หรือ
- ต้องการ reference ที่ stable เพื่อกัน
React.memochild (หรือ effect dependency) ไม่ให้รันใหม่
สำหรับค่าที่ถูก — string concat, .filter เล็ก ๆ — คำนวณตอน render ดีกว่าและชัดกว่า อย่าหยิบ useMemo มาใช้แบบอัตโนมัติ
flowchart TB render["parent re-renders"] --> newfn["new function reference created each render"] newfn --> child["memoized child sees a 'changed' prop"] child --> rerender["child re-renders needlessly"] fix["useCallback → stable reference"] --> skip["memoized child skips re-render"]
React Compiler เปลี่ยนสมการ
หัวข้อที่มีชื่อว่า “React Compiler เปลี่ยนสมการ”React มี compiler ที่ memoize component และ value ของคุณอัตโนมัติตอน build — compiler แทรกสิ่งที่เทียบเท่า useMemo/useCallback/memo ให้ตรงจุดที่ช่วยจริง โดยวิเคราะห์ code ของคุณ จุดประสงค์ทั้งหมดคือ คุณไม่ควรต้อง memoize เอง
แนวทางปฏิบัติสำหรับ project React 19+:
- เปิด compiler: เขียน code ตรงไปตรงมา อย่าโปรย
useMemo/useCallback— compiler จัดการ memoization ให้ ถูกต้องกว่าและละเอียดกว่าการจูนมือส่วนใหญ่ หน้าที่คุณคือทำให้ component pure (compiler พึ่ง Rules of Hooks และ purity เพื่อทำงานอย่างปลอดภัย) - ไม่เปิด compiler: tool มือด้านบนยังใช้ได้ — หยิบมาเฉพาะที่ bottleneck จริงที่วัดได้
ทิศทางชัดเจน: manual memoization กำลังกลายเป็น optimization ทางเลือกสุดท้าย ไม่ใช่นิสัยเริ่มต้น ทำให้ component pure แล้วให้ compiler จัดการงานจดจำให้