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

useRef & the DOM

useRef ให้ container ที่ mutable — object { current: value } — ที่ React เก็บไว้ข้าม render แต่ ไม่เฝ้าดู การเปลี่ยน ref.current ไม่ trigger re-render

const ref = useRef(0);
ref.current += 1; // mutate freely — NO re-render happens

นั่นคือความต่างทั้งหมดจาก state:

useStateuseRef
อยู่ข้าม re-render
เปลี่ยนแล้ว re-render✅ ใช่❌ ไม่
อ่านตอน render✅ (เป็น snapshot)⚠️ เลี่ยง (mutable, ไม่ reactive)
ใช้สำหรับdata ที่แสดงใน UIvalue ที่ต้องจำแต่ไม่ render

ใช้ ref สำหรับสิ่งที่ UI ไม่ได้แสดงตรง ๆ: timer id, ค่าก่อนหน้าของบางอย่าง, counter ที่ mutable, scroll position หรือ reference ไปยัง DOM node

// Classic use: hold a timer id so you can clear it later.
const intervalRef = useRef(null);
function start() {
intervalRef.current = setInterval(tick, 1000);
}
function stop() {
clearInterval(intervalRef.current);
}

การใช้บ่อยที่สุดคือคว้า DOM node — เพื่อ focus input, วัดขนาด element หรือเรียก imperative browser API ผูก ref กับ host element ผ่าน attribute ref หลัง commit ref.current จะชี้ไปยัง DOM node จริง

function SearchBox() {
const inputRef = useRef(null);
return (
<>
<input ref={inputRef} />
<button onClick={() => inputRef.current.focus()}>Focus</button>
</>
);
}

นี่คือ escape hatch — คุณกำลังก้าวออกนอก declarative model เพื่อคุยกับ DOM โดยตรง ใช้กับ focus, scroll, การวัดขนาด และการ integrate widget ที่ไม่ใช่ React อย่าใช้ทำสิ่งที่ state ทำได้

เมื่อก่อน การส่ง ref ผ่าน component ของคุณเองไปยัง DOM node ข้างในต้องห่อ component ด้วย forwardRef ใน React 19 ref เป็น prop ธรรมดา — คุณรับ ref แล้วส่งต่อได้เหมือน prop อื่น ๆ และ ไม่ต้องใช้ forwardRef สำหรับ code ใหม่แล้ว

// ✅ React 19: accept ref as a normal prop — no forwardRef.
function MyInput({ placeholder, ref }) {
return <input placeholder={placeholder} ref={ref} />;
}
// Parent:
const ref = useRef(null);
<MyInput ref={ref} placeholder="Search" />;

form เก่ายังใช้ได้ — forwardRef ไม่ได้ถูกถอดออก — แต่ตอนนี้เป็น legacy component ใหม่ควรรับ ref เป็น prop

สำหรับกรณีที่พบน้อยกว่า ที่คุณอยากเปิดเผย imperative API แบบ custom (ไม่ใช่ raw DOM node) ให้ parent useImperativeHandle ให้คุณกำหนดได้ว่า ref เปิดเผยอะไรบ้าง

function FancyInput({ ref }) {
const inputRef = useRef(null);
useImperativeHandle(ref, () => ({
focus: () => inputRef.current.focus(),
clear: () => { inputRef.current.value = ''; },
}));
return <input ref={inputRef} />;
}
ความต่างสำคัญระหว่าง useRef กับ useState คืออะไร?
อะไรคือการใช้ ref ที่เหมาะสม?
ใน React 19 คุณส่ง ref ผ่าน component ของคุณเองไปยัง DOM node ข้างในอย่างไร?
useImperativeHandle ทำอะไร?