ทำความรู้จักกับ useRef ตัวช่วยจัดการ DOM
ในการเขียน React เรามักจะให้หน้าจอเปลี่ยนไปตามข้อมูลที่เปลี่ยนไป แต่บางครั้งเราก็ต้องการเข้าถึง DOM Element (ส่วนประกอบของหน้าเว็บ เช่น กล่องข้อความ หรือปุ่ม) โดยตรงเหมือนกับการเขียน JavaScript แบบดั้งเดิม ซึ่ง useRef คือเครื่องมือที่จะเข้ามาช่วยเราในเรื่องนี้ครับ
ลองนึกภาพว่าคุณกำลังคุมงานก่อสร้าง ปกติคุณสั่งงานผ่านระบบส่วนกลาง (เหมือน State หรือสถานะข้อมูล) แต่บางทีคุณก็จำเป็นต้องเดินไปหยิบของหรือสั่งงานคนงานที่หน้างานโดยตรง useRef ก็คือการที่คุณเดินไปหยิบเครื่องมือชิ้นนั้นมาถือไว้ในมือเพื่อใช้งานได้ทันทีครับ
การใช้ useRef จะช่วยให้เราเข้าถึงคุณสมบัติของ HTML ได้โดยไม่ต้องรอให้ React สั่งวาดหน้าจอใหม่ ซึ่งถือเป็นวิธีที่สะดวกและรวดเร็วในบางสถานการณ์ที่การใช้ระบบปกติทำได้ยากครับ
วิธีใช้ useRef เพื่อสั่งงาน DOM
ขั้นตอนแรกเราต้องสร้างตัวแปรอ้างอิงขึ้นมาก่อน โดยใช้คำสั่ง useRef() แล้วนำไปผูกไว้กับ HTML Element ผ่านคุณสมบัติที่ชื่อว่า ref ครับ
เมื่อผูกเสร็จแล้ว เราจะสามารถสั่งงานผ่านตัวแปรนั้นได้ทุกเมื่อที่ต้องการ เช่น การสั่งให้ช่องกรอกข้อความเลื่อนไปโฟกัส (การทำให้เคอร์เซอร์ไปกระพริบในช่องนั้น) หรือการวัดขนาดความกว้างของกล่องข้อความครับ
ลองดูตัวอย่างการใช้งานเพื่อสั่งให้ช่องกรอกข้อความทำงานครับ:
import { useRef } from 'react';
function TextInputWithFocusButton() {
// สร้างตัวแปร ref เพื่อเก็บค่าอ้างอิง
const inputEl = useRef(null);
const onButtonClick = () => {
// สั่งโฟกัสที่ช่อง input โดยตรงผ่าน current
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>กดเพื่อโฟกัส</button>
</>
);
}
ในโค้ดนี้ inputEl.current คือตัวที่ใช้เข้าถึงตัวช่องกรอกข้อความจริงๆ ครับ
ความต่างระหว่าง useRef กับ useState
หลายคนมักสับสนว่าทำไมต้องแยก useRef กับ useState (ตัวเก็บข้อมูลที่ทำให้หน้าจอวาดใหม่) ออกจากกัน คำตอบคือเรื่องของการ Re-render (การสั่งให้หน้าจอวาดใหม่เมื่อข้อมูลเปลี่ยน) ครับ
ถ้าคุณใช้ useState ทุกครั้งที่ข้อมูลเปลี่ยน React จะสั่งวาดหน้าจอใหม่ทันทีเพื่อให้ข้อมูลบนเว็บตรงกับความจริง ซึ่งดีสำหรับการแสดงผล แต่ถ้าคุณแค่ต้องการเก็บค่าอะไรบางอย่างไว้ใช้งานเบื้องหลังโดยไม่ต้องการให้หน้าจอวาดใหม่ useRef จะตอบโจทย์กว่าครับ
ลองจินตนาการว่า useState คือการเปลี่ยนป้ายประกาศหน้าหมู่บ้านที่ทุกคนเห็น ส่วน useRef คือสมุดจดส่วนตัวที่คุณเก็บไว้ในกระเป๋าซึ่งไม่มีใครเห็นนอกจากตัวคุณเองครับ
การใช้ useRef จึงช่วยให้โปรแกรมทำงานได้เร็วขึ้น เพราะไม่ต้องเสียเวลาวาดหน้าจอใหม่ทุกครั้งที่มีการเปลี่ยนค่าที่ไม่จำเป็นต้องแสดงผลครับ
เมื่อไหร่ที่ควรใช้ useRef
คุณควรเลือกใช้ useRef เมื่อต้องการเข้าถึง DOM โดยตรง หรือต้องการเก็บค่าบางอย่างที่ ไม่ส่งผลต่อการแสดงผลบนหน้าจอ ครับ
ตัวอย่างสถานการณ์ที่เจอบ่อยคือ การจัดการ Focus (การทำให้จุดที่พิมพ์ข้อความไปอยู่ที่ช่องนั้น), การเลื่อนหน้าจอ (Scrolling), หรือการวัดขนาด (Measurement) ของกล่องข้อความที่คุณสร้างขึ้นมาครับ
นอกจากนี้ยังใช้เก็บค่าของ Timer (ตัวจับเวลา) หรือค่าก่อนหน้าเพื่อนำมาเปรียบเทียบในฟังก์ชันการทำงานได้ดีมากครับ
แต่ระวังนะครับ! ถ้าคุณต้องการให้สิ่งที่เปลี่ยนไปแสดงผลบนหน้าจอให้ผู้ใช้เห็น คุณต้องใช้ useState เท่านั้น อย่าพยายามใช้ useRef แทน เพราะหน้าจอจะไม่ยอมเปลี่ยนตามค่าที่คุณตั้งไว้ครับ
จุดที่มือใหม่มักพลาด
ข้อผิดพลาดที่พบบ่อยที่สุดคือการลืมใส่ .current เวลาเรียกใช้งานค่าใน useRef ครับ เพราะค่าที่แท้จริงของมันจะถูกเก็บอยู่ในคุณสมบัติที่ชื่อว่า current เสมอ
อีกจุดหนึ่งคือการพยายามใช้ useRef เพื่อเก็บข้อมูลที่ควรจะเป็น State เช่น ข้อมูลในฟอร์มที่ต้องอัปเดตตลอดเวลา ซึ่งจะทำให้หน้าจอไม่ยอมอัปเดตข้อมูลใหม่ให้เห็นครับ
สุดท้ายคือการเรียกใช้ ref ก่อนที่หน้าจอจะวาดเสร็จ ซึ่งจะทำให้เกิดค่าเป็น null (ค่าว่างเปล่า) เพราะ React ยังสร้าง DOM Element นั้นขึ้นมาไม่สำเร็จครับ
คำแนะนำคือให้ตรวจสอบเสมอว่าคุณต้องการให้หน้าจออัปเดตไหม ถ้าใช่ให้ใช้ useState ทันทีครับ
สรุป: เลือกใช้ให้ถูกงาน
การเข้าใจ useRef จะทำให้คุณทำงานกับ React ได้ยืดหยุ่นขึ้นมาก โดยเฉพาะเมื่อต้องจัดการกับส่วนประกอบของ HTML ที่ซับซ้อนครับ
สรุปง่ายๆ คือ useState ใช้สำหรับข้อมูลที่ต้องโชว์บนหน้าจอ ส่วน useRef ใช้สำหรับอ้างอิง DOM หรือเก็บค่าเบื้องหลังโดยไม่ต้องวาดหน้าจอใหม่ครับ
กฎเหล็กคือ อย่าใช้ useRef ถ้าคุณต้องการให้หน้าจอเปลี่ยนตามค่าที่เปลี่ยนไป การเลือกเครื่องมือให้ถูกตัวตั้งแต่เริ่มฝึก จะช่วยให้คุณประหยัดเวลาแก้บั๊ก (ข้อผิดพลาดของโปรแกรม) ได้มหาศาลครับ