จัดการ DOM และเก็บค่าประจำ instance ด้วย useRef โดยไม่ทำลายความ pure ของการ render
เปิดบทเรียนนี้ใน KodokonuseRef คืนกล่องที่แก้ไขได้ - object ที่มี property current เพียงตัวเดียว - ซึ่ง identity ของมันอยู่รอดผ่านทุก render ความแตกต่างพื้นฐานสองอย่างจาก state: การแก้ไข ref.current ไม่ trigger การ re-render และการเปลี่ยนแปลงมองเห็นได้ทันทีโดยไม่ต้องรอ render ถัดไป การใช้งานสองกลุ่มจึงตามมา: การอ้างถึง DOM node และการเก็บค่าประจำ instance ที่ต้องอยู่รอดผ่านการ render โดยไม่ขับเคลื่อนการแสดงผล
import { useEffect, useRef } from "react";
function SearchField() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus();
}, []);
return <input ref={inputRef} type="search" />;
}ในด้านค่าประจำ instance สิ่งใดก็ตามที่ต้องคงอยู่โดยไม่ก่อให้เกิดการ render ควรอยู่ใน ref: id ที่คืนมาจาก setInterval, instance ของไลบรารีภายนอก (แผนที่, editor, video player) หรือค่าจาก render ก่อนหน้า กฎทองยังคงเหมือนเดิม: การ render ต้องเป็นฟังก์ชัน pure ของ props และ state ref ถูกอ่านและเขียนใน effect และ event handler ไม่ใช่ระหว่างการ render
import { useEffect, useRef } from "react";
function usePrevious(value) {
const ref = useRef(undefined);
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
}ในการเปิดเผย DOM node จาก component ของคุณเอง ให้ส่ง ref ต่อไป: ตั้งแต่ React 19 เป็นต้นมา ref เป็น prop ธรรมดาของ function component; ก่อนหน้านั้น การผ่าน forwardRef เป็นสิ่งจำเป็น สัญชาตญาณสุดท้ายที่ควรฝึก: เลือกวิธีแบบ declarative เมื่อ state เพียงพอที่จะอธิบายผลลัพธ์ (CSS class, attribute disabled) สงวน ref ไว้สำหรับดินแดนที่ React ไม่ครอบคลุม: focus, การเลือกข้อความ, การวัดขนาด element, การเลื่อน, การเล่นสื่อ
import { useRef } from "react";
function TextField({ ref, ...props }) {
return <input ref={ref} {...props} />;
}
function Form() {
const fieldRef = useRef(null);
return (
<>
<TextField ref={fieldRef} />
<button onClick={() => fieldRef.current.focus()}>
Give focus
</button>
</>
);
}