ไทย

คู่มือฉบับสมบูรณ์เกี่ยวกับ React Refs โดยเน้นที่ useRef และ createRef เรียนรู้วิธีและเวลาที่ควรใช้แต่ละตัวเพื่อการจัดการคอมโพเนนต์และการเข้าถึง DOM อย่างมีประสิทธิภาพในแอปพลิเคชันระดับโลก

React Refs: ไขข้อข้องใจความแตกต่างระหว่าง useRef และ createRef

ในโลกของการพัฒนา React ที่ไม่เคยหยุดนิ่ง การจัดการสถานะของคอมโพเนนต์ (component state) และการโต้ตอบกับ Document Object Model (DOM) อย่างมีประสิทธิภาพเป็นสิ่งสำคัญอย่างยิ่ง React Refs เป็นกลไกที่ช่วยให้สามารถเข้าถึงและจัดการ DOM elements หรือ React components ได้โดยตรง สองวิธีหลักในการสร้าง Refs คือ useRef และ createRef แม้ว่าทั้งสองจะทำหน้าที่สร้าง Refs เหมือนกัน แต่ก็มีความแตกต่างในการใช้งานและกรณีการใช้งาน คู่มือนี้มีจุดมุ่งหมายเพื่อไขข้อข้องใจเกี่ยวกับสองวิธีนี้ เพื่อให้เกิดความชัดเจนว่าเมื่อใดและอย่างไรควรใช้แต่ละวิธีอย่างมีประสิทธิภาพในโปรเจกต์ React ของคุณ โดยเฉพาะอย่างยิ่งเมื่อพัฒนาสำหรับผู้ใช้ทั่วโลก

ทำความเข้าใจ React Refs

Ref (ย่อมาจาก reference) เป็นฟีเจอร์ของ React ที่ช่วยให้คุณสามารถเข้าถึง DOM node หรือ React component ได้โดยตรง สิ่งนี้มีประโยชน์อย่างยิ่งเมื่อคุณต้องการ:

แม้ว่า React จะสนับสนุนแนวทางแบบ declarative ซึ่ง UI จะถูกจัดการผ่าน state และ props แต่ก็มีบางสถานการณ์ที่จำเป็นต้องมีการจัดการโดยตรง Refs เป็นสะพานเชื่อมระหว่างธรรมชาติแบบ declarative ของ React กับการดำเนินการกับ DOM แบบ imperative

createRef: แนวทางสำหรับ Class Component

createRef เป็นเมธอดที่ React มีให้ใช้ โดยหลักแล้วจะใช้ภายใน class components เพื่อสร้าง Refs ทุกครั้งที่ class component ถูกสร้างขึ้นมา (instantiated) createRef จะสร้างอ็อบเจกต์ Ref ใหม่ขึ้นมาเสมอ สิ่งนี้ช่วยให้แน่ใจว่าแต่ละ instance ของคอมโพเนนต์มี Ref ที่เป็นเอกลักษณ์ของตัวเอง

Syntax และการใช้งาน

ในการใช้ createRef คุณจะต้องประกาศ Ref ใน class component ของคุณก่อน โดยทั่วไปจะทำใน constructor จากนั้นคุณก็นำ Ref ไปผูกกับ DOM element หรือคอมโพเนนต์โดยใช้ attribute ที่ชื่อว่า ref


class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }

  componentDidMount() {
    // เข้าถึง DOM element หลังจากคอมโพเนนต์เมาท์แล้ว
    this.myRef.current.focus();
  }

  render() {
    return ;
  }
}

ในตัวอย่างนี้ this.myRef ถูกสร้างขึ้นโดยใช้ React.createRef() จากนั้นจึงถูกกำหนดให้กับ attribute ref ของ element input หลังจากที่คอมโพเนนต์เมาท์แล้ว (ใน componentDidMount) คุณสามารถเข้าถึง DOM node จริงได้โดยใช้ this.myRef.current และดำเนินการกับมันได้ (ในกรณีนี้คือการโฟกัสที่ input)

ตัวอย่าง: การโฟกัสช่อง Input

ลองพิจารณาสถานการณ์ที่คุณต้องการโฟกัสช่อง input โดยอัตโนมัติเมื่อคอมโพเนนต์เมาท์ นี่เป็นกรณีการใช้งานทั่วไปสำหรับ Refs โดยเฉพาะในฟอร์มหรือองค์ประกอบที่มีการโต้ตอบ


class FocusInput extends React.Component {
  constructor(props) {
    super(props);
    this.inputRef = React.createRef();
  }

  componentDidMount() {
    this.inputRef.current.focus();
  }

  render() {
    return (
      
); } }

ในตัวอย่างนี้ FocusInput จะโฟกัสที่ช่อง input ทันทีหลังจากที่เมาท์แล้ว ซึ่งสามารถปรับปรุงประสบการณ์ของผู้ใช้โดยการดึงดูดความสนใจของผู้ใช้ไปยัง element input ทันทีที่คอมโพเนนต์ถูกเรนเดอร์

ข้อควรพิจารณาที่สำคัญเกี่ยวกับ createRef

useRef: Hook สำหรับ Functional Component

useRef เป็น Hook ที่ถูกนำมาใช้ใน React 16.8 มันเป็นวิธีในการสร้างอ็อบเจกต์ Ref ที่เปลี่ยนแปลงค่าได้ (mutable) ภายใน functional components ซึ่งแตกต่างจาก createRef ตรงที่ useRef จะคืนค่าอ็อบเจกต์ Ref เดิมทุกครั้งที่คอมโพเนนต์เรนเดอร์ ทำให้เหมาะอย่างยิ่งสำหรับการเก็บค่าไว้ตลอดการ re-render โดยไม่ทำให้เกิดการ re-render ซ้ำ

Syntax และการใช้งาน

การใช้ useRef นั้นตรงไปตรงมา คุณเรียกใช้ useRef Hook โดยส่งค่าเริ่มต้นเข้าไป Hook จะคืนค่าอ็อบเจกต์ที่มี property .current ซึ่งคุณสามารถใช้เพื่อเข้าถึงและแก้ไขค่าได้


import React, { useRef, useEffect } from 'react';

function MyFunctionalComponent() {
  const myRef = useRef(null);

  useEffect(() => {
    // เข้าถึง DOM element หลังจากคอมโพเนนต์เมาท์แล้ว
    if (myRef.current) {
      myRef.current.focus();
    }
  }, []);

  return ;
}

ในตัวอย่างนี้ useRef(null) สร้าง Ref ที่มีค่าเริ่มต้นเป็น null useEffect Hook ถูกใช้เพื่อเข้าถึง DOM element หลังจากที่คอมโพเนนต์เมาท์แล้ว property myRef.current จะเก็บการอ้างอิงไปยัง element input ทำให้คุณสามารถโฟกัสได้

ตัวอย่าง: การติดตามค่า Prop ก่อนหน้า

หนึ่งในกรณีการใช้งานที่ทรงพลังของ useRef คือการติดตามค่าก่อนหน้าของ prop เนื่องจากการเปลี่ยนแปลงค่าใน Refs ไม่ได้ทำให้เกิดการ re-render คุณจึงสามารถใช้มันเพื่อเก็บค่าที่คุณต้องการให้คงอยู่ตลอดการ re-render โดยไม่ส่งผลกระทบต่อ UI


import React, { useRef, useEffect } from 'react';

function PreviousValueComponent({ value }) {
  const previousValue = useRef();

  useEffect(() => {
    previousValue.current = value;
  }, [value]);

  return (
    

Current Value: {value}

Previous Value: {previousValue.current}

); }

ในตัวอย่างนี้ previousValue.current จะเก็บค่าก่อนหน้าของ prop ที่ชื่อ value useEffect Hook จะอัปเดต Ref ทุกครั้งที่ prop value เปลี่ยนแปลง ซึ่งช่วยให้คุณสามารถเปรียบเทียบค่าปัจจุบันและค่าก่อนหน้าได้ ซึ่งมีประโยชน์สำหรับการตรวจจับการเปลี่ยนแปลงหรือการสร้างแอนิเมชัน

ข้อควรพิจารณาที่สำคัญเกี่ยวกับ useRef

useRef vs. createRef: การเปรียบเทียบโดยละเอียด

หลังจากที่เราได้สำรวจทั้ง useRef และ createRef แยกกันแล้ว มาเปรียบเทียบกันแบบตัวต่อตัวเพื่อเน้นย้ำถึงความแตกต่างที่สำคัญและเมื่อใดควรเลือกใช้อันไหน

คุณสมบัติ useRef createRef
ประเภทคอมโพเนนต์ Functional Components Class Components
Hook หรือ Method Hook Method
Ref Instance คืนค่าอ็อบเจกต์ Ref เดิมในทุกการเรนเดอร์ สร้างอ็อบเจกต์ Ref ใหม่ในทุก instance ของคอมโพเนนต์
กรณีการใช้งาน
  • การเข้าถึง DOM elements
  • การเก็บค่าไว้ตลอดการ re-render โดยไม่ทำให้เกิดการ re-render ซ้ำ
  • การติดตามค่า prop ก่อนหน้า
  • การเก็บค่าที่เปลี่ยนแปลงได้ซึ่งไม่ทำให้เกิดการ re-render
  • การเข้าถึง DOM elements
  • การเข้าถึงเมธอดของ child component

การเลือก Ref ที่เหมาะสม: คู่มือการตัดสินใจ

นี่คือคู่มือง่ายๆ ที่จะช่วยให้คุณเลือกระหว่าง useRef และ createRef:

นอกเหนือจากการจัดการ DOM: กรณีการใช้งานขั้นสูงสำหรับ Refs

ในขณะที่การเข้าถึงและจัดการ DOM elements เป็นกรณีการใช้งานหลักของ Refs แต่พวกมันยังมีความสามารถที่นอกเหนือไปจากฟังก์ชันหลักนี้ มาสำรวจสถานการณ์ขั้นสูงบางอย่างที่ Refs สามารถมีประโยชน์เป็นพิเศษได้

1. การเข้าถึงเมธอดของ Child Component

Refs สามารถใช้เพื่อเข้าถึงเมธอดที่กำหนดไว้ใน child components ได้ ซึ่งช่วยให้ parent component สามารถสั่งการทำงานหรือดึงข้อมูลจาก children ได้โดยตรง แนวทางนี้มีประโยชน์อย่างยิ่งเมื่อคุณต้องการควบคุม child components อย่างละเอียด


class ParentComponent extends React.Component {
  constructor(props) {
    super(props);
    this.childRef = React.createRef();
  }

  handleClick = () => {
    // เรียกใช้เมธอดบน child component
    this.childRef.current.doSomething();
  };

  render() {
    return (
      
); } } class ChildComponent extends React.Component { doSomething = () => { console.log('Child component action triggered!'); }; render() { return
This is a child component.
; } }

ในตัวอย่างนี้ ParentComponent ใช้ Ref เพื่อเข้าถึง ChildComponent และเรียกใช้เมธอด doSomething ของมัน

2. การจัดการโฟกัสและการเลือก

Refs มีค่าอย่างยิ่งสำหรับการจัดการโฟกัสและการเลือกภายในช่อง input และองค์ประกอบเชิงโต้ตอบอื่นๆ นี่เป็นสิ่งสำคัญสำหรับการสร้างอินเทอร์เฟซที่เข้าถึงได้และเป็นมิตรต่อผู้ใช้


import React, { useRef, useEffect } from 'react';

function FocusOnMount() {
  const inputRef = useRef(null);

  useEffect(() => {
    if (inputRef.current) {
      inputRef.current.focus();
      inputRef.current.select(); // เลือกข้อความใน input
    }
  }, []);

  return ;
}

ตัวอย่างนี้จะโฟกัสที่ input และเลือกข้อความทันทีที่คอมโพเนนต์เมาท์

3. การสร้างแอนิเมชันให้กับ Elements

Refs สามารถใช้ร่วมกับไลบรารีแอนิเมชัน (เช่น GreenSock หรือ Framer Motion) เพื่อจัดการ DOM โดยตรงและสร้างแอนิเมชันที่ซับซ้อน ซึ่งช่วยให้สามารถควบคุมลำดับของแอนิเมชันได้อย่างละเอียด

ตัวอย่างโดยใช้ JavaScript พื้นฐานเพื่อความเรียบง่าย:


import React, { useRef, useEffect } from 'react';

function AnimatedBox() {
  const boxRef = useRef(null);

  useEffect(() => {
    const box = boxRef.current;
    if (box) {
      // แอนิเมชันง่ายๆ: ย้ายกล่องไปทางขวา
      box.animate(
        [
          { transform: 'translateX(0)' },
          { transform: 'translateX(100px)' },
        ],
        {
          duration: 1000, // 1 วินาที
          iterations: Infinity, // เล่นซ้ำตลอดไป
          direction: 'alternate',
        }
      );
    }
  }, []);

  return 
; }

ตัวอย่างนี้ใช้ Web Animations API เพื่อสร้างแอนิเมชันให้กับกล่องธรรมดา โดยย้ายไปมาในแนวนอน

แนวทางปฏิบัติที่ดีที่สุดสำหรับการใช้ React Refs ในแอปพลิเคชันระดับโลก

เมื่อพัฒนาแอปพลิเคชัน React สำหรับผู้ใช้ทั่วโลก สิ่งสำคัญคือต้องพิจารณาว่า Refs มีปฏิสัมพันธ์กับการทำ Internationalization (i18n) และ Localization (l10n) อย่างไร นี่คือแนวทางปฏิบัติที่ดีที่สุดบางส่วน:

1. การเข้าถึงได้ (Accessibility - A11y)

ตรวจสอบให้แน่ใจว่าการใช้ Refs ของคุณไม่ส่งผลเสียต่อการเข้าถึงได้ ตัวอย่างเช่น เมื่อทำการโฟกัส elements ด้วยโปรแกรม ให้พิจารณาลำดับการโฟกัสของผู้ใช้ และพิจารณาว่าการเปลี่ยนแปลงโฟกัสนั้นเหมาะสมสำหรับโปรแกรมอ่านหน้าจอและผู้ใช้คีย์บอร์ดหรือไม่


import React, { useRef, useEffect } from 'react';

function AccessibleFocus() {
  const buttonRef = useRef(null);

  useEffect(() => {
    const button = buttonRef.current;
    if (button) {
      // โฟกัสเฉพาะเมื่อผู้ใช้ยังไม่ได้โฟกัสที่ปุ่ม
      if (document.activeElement !== button) {
        button.focus();
      }
    }
  }, []);

  return ;
}

2. ช่อง Input ที่รองรับหลายภาษา (Internationalized Input Fields)

เมื่อทำงานกับช่อง input โปรดระวังวิธีการป้อนข้อมูลและชุดอักขระที่แตกต่างกันในแต่ละภาษา ตรวจสอบให้แน่ใจว่าการจัดการผ่าน Ref ของคุณ (เช่น การเลือก, ตำแหน่งเคอร์เซอร์) ทำงานได้อย่างถูกต้องกับประเภทการป้อนข้อมูลและภาษาต่างๆ ทดสอบคอมโพเนนต์ของคุณอย่างละเอียดกับภาษาและวิธีการป้อนข้อมูลที่แตกต่างกัน

3. เลย์เอาต์แบบขวาไปซ้าย (Right-to-Left - RTL)

หากแอปพลิเคชันของคุณรองรับภาษา RTL (เช่น ภาษาอาหรับ, ฮีบรู) ตรวจสอบให้แน่ใจว่าการจัดการ DOM ของคุณโดยใช้ Refs คำนึงถึงเลย์เอาต์ที่กลับด้านด้วย ตัวอย่างเช่น เมื่อสร้างแอนิเมชันให้กับ elements ให้พิจารณาการกลับทิศทางของแอนิเมชันสำหรับภาษา RTL

4. ข้อควรพิจารณาด้านประสิทธิภาพ

แม้ว่า Refs จะเป็นวิธีที่ทรงพลังในการโต้ตอบกับ DOM แต่การใช้งานมากเกินไปอาจนำไปสู่ปัญหาด้านประสิทธิภาพได้ การจัดการ DOM โดยตรงจะข้ามกระบวนการ virtual DOM และ reconciliation ของ React ซึ่งอาจนำไปสู่ความไม่สอดคล้องกันและการอัปเดตที่ช้าลง ใช้ Refs อย่างรอบคอบและเฉพาะเมื่อจำเป็นเท่านั้น

สรุป

React Refs โดยเฉพาะ useRef และ createRef เป็นเครื่องมือที่จำเป็นสำหรับนักพัฒนา React การทำความเข้าใจความแตกต่างของแต่ละวิธีและเวลาที่จะนำไปใช้อย่างมีประสิทธิภาพเป็นสิ่งสำคัญสำหรับการสร้างแอปพลิเคชันที่แข็งแกร่งและมีประสิทธิภาพ createRef ยังคงเป็นมาตรฐานสำหรับการจัดการ Refs ภายใน class components เพื่อให้แน่ใจว่าแต่ละ instance มี Ref ที่เป็นเอกลักษณ์ของตัวเอง ส่วน useRef ด้วยธรรมชาติที่คงอยู่ตลอดการ re-render จึงเหมาะสำหรับ functional components โดยเป็นวิธีในการจัดการ DOM elements และเก็บค่าไว้โดยไม่ทำให้เกิดการ re-render ที่ไม่จำเป็น ด้วยการใช้เครื่องมือเหล่านี้อย่างชาญฉลาด คุณสามารถเพิ่มฟังก์ชันการทำงานและประสบการณ์ผู้ใช้ของแอปพลิเคชัน React ของคุณ เพื่อตอบสนองผู้ใช้ทั่วโลกด้วยอินเทอร์เฟซที่เข้าถึงได้และมีประสิทธิภาพ

ในขณะที่ React ยังคงพัฒนาต่อไป การเชี่ยวชาญแนวคิดพื้นฐานเหล่านี้จะช่วยให้คุณสามารถสร้างประสบการณ์เว็บที่เป็นนวัตกรรมและเป็นมิตรต่อผู้ใช้ซึ่งก้าวข้ามขอบเขตทางภูมิศาสตร์และวัฒนธรรม อย่าลืมให้ความสำคัญกับการเข้าถึงได้ (accessibility), การรองรับหลายภาษา (internationalization) และประสิทธิภาพ (performance) เพื่อส่งมอบแอปพลิเคชันระดับโลกอย่างแท้จริง