ปลดล็อกพลังของ createRef ใน React เพื่อเข้าถึง DOM และโต้ตอบกับคอมโพเนนต์โดยตรง คู่มือนี้มีตัวอย่างที่ใช้ได้จริงและแนวทางปฏิบัติที่ดีที่สุดสำหรับนักพัฒนาทั่วโลก
เชี่ยวชาญ React createRef: คู่มือฉบับสมบูรณ์สำหรับการพัฒนายุคใหม่
ในโลกของการพัฒนาฟรอนต์เอนด์ที่เปลี่ยนแปลงตลอดเวลา React โดดเด่นในฐานะไลบรารี JavaScript ที่ทรงพลังและหลากหลายสำหรับการสร้างส่วนติดต่อผู้ใช้ (user interfaces) หนึ่งในคุณสมบัติหลักที่ช่วยให้นักพัฒนา React สามารถโต้ตอบกับ Document Object Model (DOM) ได้โดยตรงและจัดการพฤติกรรมของคอมโพเนนต์คือ createRef
API คู่มือนี้จะเจาะลึกถึงรายละเอียดของ createRef
เพื่อให้ความเข้าใจที่ครอบคลุมเกี่ยวกับการใช้งาน ประโยชน์ และแนวทางปฏิบัติที่ดีที่สุดสำหรับนักพัฒนาทั่วโลก
ทำความเข้าใจ React Refs
ก่อนที่จะเจาะลึกถึง createRef
สิ่งสำคัญคือต้องเข้าใจแนวคิดของ refs ใน React ก่อน ref เป็นวิธีการเข้าถึงโหนด DOM หรือองค์ประกอบ React ที่สร้างขึ้นในเมธอด render การเข้าถึงนี้ช่วยให้คุณสามารถดำเนินการต่างๆ เช่น การโฟกัสช่องป้อนข้อมูล การกระตุ้นแอนิเมชั่น หรือการวัดขนาดขององค์ประกอบ
ต่างจากการจัดการ DOM ด้วย JavaScript แบบดั้งเดิม refs ใน React มีวิธีการโต้ตอบกับ DOM ที่ควบคุมได้และมีประสิทธิภาพ Virtual DOM ของ React ได้ซ่อนความซับซ้อนของการจัดการ DOM โดยตรงไว้มากมาย แต่ refs ทำหน้าที่เป็นสะพานเชื่อมเมื่อจำเป็นต้องเข้าถึงโดยตรง
แนะนำ createRef
createRef
เป็นฟังก์ชันที่ React มีให้เพื่อสร้างอ็อบเจ็กต์ ref อ็อบเจ็กต์ ref นี้มีคุณสมบัติ current
ซึ่งเก็บโหนด DOM หรืออินสแตนซ์ของคอมโพเนนต์ React ที่ ref นั้นถูกแนบอยู่ createRef
API ถูกนำมาใช้ใน React 16.3 และเป็นวิธีที่แนะนำในการสร้าง refs ใน class components สำหรับ functional components นั้น useRef
(React Hook) ก็ให้ฟังก์ชันการทำงานที่คล้ายกัน
การสร้าง Ref Object
หากต้องการสร้างอ็อบเจ็กต์ ref เพียงแค่เรียกใช้ฟังก์ชัน createRef()
:
import React from 'react';
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return (
);
}
}
ในตัวอย่างนี้ this.myRef
เป็นอ็อบเจ็กต์ ref ที่ถูกกำหนดให้กับ attribute ref
ขององค์ประกอบ input คุณสมบัติ current
ของ this.myRef
จะเก็บการอ้างอิงไปยังองค์ประกอบ input หลังจากที่คอมโพเนนต์ถูก mount แล้ว
การเข้าถึงโหนด DOM
เมื่อคอมโพเนนต์ถูก mount แล้ว คุณสามารถเข้าถึงโหนด DOM ผ่านคุณสมบัติ current
ของอ็อบเจ็กต์ ref:
import React from 'react';
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
this.focusInput = this.focusInput.bind(this);
}
componentDidMount() {
this.focusInput();
}
focusInput() {
this.myRef.current.focus();
}
render() {
return (
);
}
}
ในตัวอย่างนี้ เมธอด focusInput
ใช้ this.myRef.current
เพื่อเข้าถึงองค์ประกอบ input และเรียกใช้เมธอด focus()
ของมัน ซึ่งจะทำการโฟกัสช่องป้อนข้อมูลโดยอัตโนมัติเมื่อคอมโพเนนต์ถูก mount
กรณีการใช้งานสำหรับ createRef
createRef
มีประโยชน์ในสถานการณ์ต่างๆ ที่ต้องการการจัดการ DOM โดยตรงหรือการเข้าถึงอินสแตนซ์ของคอมโพเนนต์ นี่คือกรณีการใช้งานทั่วไปบางส่วน:
- การโฟกัสช่องป้อนข้อความ: ดังที่แสดงในตัวอย่างก่อนหน้านี้
createRef
มักใช้เพื่อโฟกัสช่องป้อนข้อความด้วยโปรแกรม ซึ่งมีประโยชน์ในการปรับปรุงประสบการณ์ของผู้ใช้โดยการโฟกัสช่องป้อนข้อมูลแรกในฟอร์มโดยอัตโนมัติ หรือโฟกัสช่องป้อนข้อมูลหลังจากการกระทำบางอย่าง - การจัดการการเล่นสื่อ: Refs สามารถใช้เพื่อควบคุมองค์ประกอบสื่อ เช่น
<video>
หรือ<audio>
คุณสามารถใช้ refs เพื่อเล่น หยุดชั่วคราว หรือปรับระดับเสียงขององค์ประกอบสื่อได้ ตัวอย่างเช่น:import React from 'react'; class VideoPlayer extends React.Component { constructor(props) { super(props); this.videoRef = React.createRef(); this.playVideo = this.playVideo.bind(this); } playVideo() { this.videoRef.current.play(); } render() { return (
- การกระตุ้นแอนิเมชั่น: Refs สามารถใช้เพื่อเข้าถึงองค์ประกอบ DOM และกระตุ้นแอนิเมชั่นโดยใช้ JavaScript หรือ CSS ซึ่งช่วยให้คุณสามารถสร้างแอนิเมชั่นที่ซับซ้อนและโต้ตอบได้ซึ่งตอบสนองต่อการกระทำของผู้ใช้
import React from 'react'; class AnimatedBox extends React.Component { constructor(props) { super(props); this.boxRef = React.createRef(); this.animate = this.animate.bind(this); } animate() { const box = this.boxRef.current; box.classList.add('animate'); } render() { return (
ในตัวอย่างนี้ การคลิกปุ่มจะเพิ่มคลาส
animate
ให้กับองค์ประกอบ box ซึ่งจะกระตุ้นแอนิเมชั่น CSS - การวัดขนาดและตำแหน่งขององค์ประกอบ: Refs มีประโยชน์ในการรับขนาดและตำแหน่งขององค์ประกอบ DOM ข้อมูลนี้สามารถใช้สำหรับการคำนวณเค้าโครง การจัดสไตล์แบบไดนามิก หรือการสร้างองค์ประกอบแบบโต้ตอบ
import React from 'react'; class SizeReporter extends React.Component { constructor(props) { super(props); this.elementRef = React.createRef(); this.state = { width: 0, height: 0 }; this.reportSize = this.reportSize.bind(this); } componentDidMount() { this.reportSize(); } reportSize() { const element = this.elementRef.current; this.setState({ width: element.offsetWidth, height: element.offsetHeight }); } render() { return (
Width: {this.state.width}px, Height: {this.state.height}px
คอมโพเนนต์นี้จะรายงานความกว้างและความสูงของ div หลังจากที่มันถูก mount แล้ว
- การทำงานร่วมกับไลบรารีของบุคคลที่สาม: Refs มักใช้เพื่อรวมคอมโพเนนต์ React เข้ากับไลบรารีของบุคคลที่สามที่ต้องการการเข้าถึง DOM โดยตรง ตัวอย่างเช่น คุณอาจใช้ ref เพื่อเข้าถึงองค์ประกอบ DOM และเริ่มต้นปลั๊กอิน jQuery บนองค์ประกอบนั้น
import React from 'react'; import $ from 'jquery'; class MyComponent extends React.Component { constructor(props) { super(props); this.elementRef = React.createRef(); } componentDidMount() { $(this.elementRef.current).plugin(); // Initialize jQuery plugin } render() { return ; } }
createRef
เปรียบเทียบกับ Callback Refs
ก่อนที่จะมีการนำ createRef
มาใช้ callback refs เป็นวิธีทั่วไปในการเข้าถึงโหนด DOM ใน React แม้ว่า callback refs จะยังคงใช้งานได้ แต่ createRef
เสนอแนวทางที่ตรงไปตรงมาและกระชับกว่า โดยเฉพาะใน class components
callback ref คือฟังก์ชันที่ React เรียกใช้โดยมีโหนด DOM หรืออินสแตนซ์ของคอมโพเนนต์เป็นอาร์กิวเมนต์ คุณกำหนดฟังก์ชันนี้ให้กับ attribute ref
ขององค์ประกอบ:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = null;
this.setRef = element => {
this.myRef = element;
};
}
componentDidMount() {
if (this.myRef) {
this.myRef.focus();
}
}
render() {
return ;
}
}
แม้ว่าแนวทางนี้จะใช้งานได้ แต่ก็อาจมีความซับซ้อนในการจัดการมากกว่า โดยเฉพาะเมื่อต้องจัดการกับ refs หลายตัว createRef
ทำให้กระบวนการนี้ง่ายขึ้นโดยการจัดหาอ็อบเจ็กต์ ref ที่สร้างขึ้นมาโดยเฉพาะ
ความแตกต่างที่สำคัญ:
- ความสามารถในการอ่าน (Readability): โดยทั่วไปแล้ว
createRef
ถือว่าอ่านง่ายและเข้าใจง่ายกว่า - ความสอดคล้อง (Consistency):
createRef
ให้วิธีการสร้างและเข้าถึง refs ที่สอดคล้องกัน - ประสิทธิภาพ (Performance): ในบางกรณี callback refs อาจทำให้เกิดการ re-render ที่ไม่จำเป็น เนื่องจากฟังก์ชัน callback เป็นฟังก์ชันใหม่ทุกครั้งที่ render แต่
createRef
หลีกเลี่ยงปัญหานี้
แนวทางปฏิบัติที่ดีที่สุดสำหรับการใช้ createRef
เพื่อให้มั่นใจถึงประสิทธิภาพสูงสุดและความสามารถในการบำรุงรักษา ให้ปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดเหล่านี้เมื่อใช้ createRef
:
- ใช้
createRef
ใน Class Components:createRef
ถูกออกแบบมาเพื่อใช้ใน class components สำหรับ functional components ให้ใช้useRef
Hook - หลีกเลี่ยงการใช้ Refs มากเกินไป: ควรใช้ Refs เท่าที่จำเป็น การใช้ refs มากเกินไปอาจนำไปสู่โค้ดที่ดูแลรักษาและทำความเข้าใจได้ยาก ควรเลือกใช้วิธีการแบบ declarative เมื่อทำได้
- การตรวจสอบค่า Null: ตรวจสอบเสมอว่าคุณสมบัติ
current
ของ ref เป็น null หรือไม่ก่อนที่จะเข้าถึง โดยเฉพาะใน lifecycle methodcomponentDidMount
โหนด DOM อาจยังไม่พร้อมใช้งานทันทีหลังจากที่คอมโพเนนต์ถูก mountcomponentDidMount() { if (this.myRef.current) { this.myRef.current.focus(); } }
- หลีกเลี่ยงการแก้ไข DOM โดยตรง: แม้ว่า refs จะให้การเข้าถึง DOM แต่ควรหลีกเลี่ยงการแก้ไข DOM โดยตรงเว้นแต่จะจำเป็นจริงๆ Virtual DOM ของ React มีวิธีที่มีประสิทธิภาพในการอัปเดต UI และการจัดการ DOM โดยตรงอาจไปรบกวนกระบวนการเรนเดอร์ของ React
- ทำความสะอาด Refs เมื่อจำเป็น: ในบางกรณี คุณอาจต้องทำความสะอาด refs เมื่อคอมโพเนนต์ถูก unmount ซึ่งมีความสำคัญอย่างยิ่งเมื่อต้องจัดการกับไลบรารีของบุคคลที่สามที่อาจมีการอ้างอิงถึงองค์ประกอบ DOM ค้างไว้
createRef
ใน Functional Components ด้วย Hooks
แม้ว่า createRef
จะใช้เป็นหลักใน class components แต่ functional components ก็สามารถบรรลุฟังก์ชันการทำงานที่คล้ายกันได้โดยใช้ useRef
Hook useRef
จะส่งคืนอ็อบเจ็กต์ ref ที่เปลี่ยนแปลงค่าได้ซึ่งคุณสมบัติ .current
ของมันจะถูกเริ่มต้นด้วยอาร์กิวเมนต์ที่ส่งเข้ามา (initialValue
) อ็อบเจ็กต์ที่ส่งคืนจะคงอยู่ตลอดอายุการใช้งานของคอมโพเนนต์
import React, { useRef, useEffect } from 'react';
function MyFunctionalComponent() {
const inputRef = useRef(null);
useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
}
}, []);
return ;
}
ในตัวอย่างนี้ useRef(null)
สร้างอ็อบเจ็กต์ ref ซึ่งถูกกำหนดให้กับตัวแปร inputRef
useEffect
Hook ถูกใช้เพื่อโฟกัสช่องป้อนข้อมูลหลังจากที่คอมโพเนนต์ได้ render แล้ว dependency array ที่ว่างเปล่า []
ทำให้แน่ใจว่า effect จะทำงานเพียงครั้งเดียวหลังจากการ render ครั้งแรก
กรณีการใช้งานขั้นสูงและข้อควรพิจารณา
นอกเหนือจากกรณีการใช้งานพื้นฐานแล้ว createRef
ยังสามารถนำไปใช้ในสถานการณ์ที่ซับซ้อนยิ่งขึ้นได้:
- การส่งต่อ Refs (Forwarding Refs): React มีกลไกที่เรียกว่า
React.forwardRef
ที่ช่วยให้คุณสามารถส่ง ref ผ่านคอมโพเนนต์ไปยังหนึ่งใน children ของมันได้ สิ่งนี้มีประโยชน์เมื่อคุณต้องการเข้าถึงโหนด DOM ภายใน child component จาก parent componentimport React, { forwardRef } from 'react'; const FancyInput = forwardRef((props, ref) => ( )); class ParentComponent extends React.Component { constructor(props) { super(props); this.inputRef = React.createRef(); } componentDidMount() { this.inputRef.current.focus(); } render() { return
; } } ในตัวอย่างนี้ คอมโพเนนต์
FancyInput
ใช้forwardRef
เพื่อส่งต่อ ref ไปยังองค์ประกอบ input ที่อยู่ภายใน จากนั้นParentComponent
ก็สามารถเข้าถึงและจัดการองค์ประกอบ input ผ่าน ref ได้ - Higher-Order Components (HOCs): เมื่อใช้ Higher-Order Components (HOCs) คุณอาจต้องจัดการ refs อย่างระมัดระวัง หาก HOC ครอบคอมโพเนนต์ที่ใช้ refs คุณต้องแน่ใจว่า refs ถูกส่งต่อไปอย่างถูกต้อง
import React, { forwardRef } from 'react'; function withRef(WrappedComponent) { const WithRef = forwardRef((props, ref) => { return
; }); WithRef.displayName = `withRef(${WrappedComponent.displayName || WrappedComponent.name || 'Component'})`; return WithRef; } class MyComponent extends React.Component { render() { return My Component; } } const EnhancedComponent = withRef(MyComponent); - Server-Side Rendering (SSR): เมื่อใช้การเรนเดอร์ฝั่งเซิร์ฟเวอร์ โปรดทราบว่า refs อาจไม่พร้อมใช้งานในระหว่างการเรนเดอร์ครั้งแรกบนเซิร์ฟเวอร์ เนื่องจาก DOM ไม่พร้อมใช้งานบนเซิร์ฟเวอร์ คุณควรเข้าถึง refs หลังจากที่คอมโพเนนต์ถูก mount บน client แล้วเท่านั้น
สรุป
createRef
เป็นเครื่องมือที่ทรงพลังสำหรับการเข้าถึงโหนด DOM และอินสแตนซ์ของคอมโพเนนต์ใน React ด้วยการทำความเข้าใจการใช้งาน ประโยชน์ และแนวทางปฏิบัติที่ดีที่สุด คุณจะสามารถใช้ประโยชน์จาก refs ได้อย่างมีประสิทธิภาพเพื่อสร้างส่วนติดต่อผู้ใช้ที่มีการโต้ตอบและไดนามิกมากขึ้น ไม่ว่าคุณจะทำการโฟกัสช่องป้อนข้อความ จัดการการเล่นสื่อ หรือทำงานร่วมกับไลบรารีของบุคคลที่สาม createRef
ก็มีวิธีการโต้ตอบกับ DOM ที่ควบคุมได้และมีประสิทธิภาพ
อย่าลืมใช้ createRef
อย่างรอบคอบ โดยเลือกใช้วิธีการแบบ declarative เมื่อเป็นไปได้ ด้วยการปฏิบัติตามแนวทางที่ระบุไว้ในคู่มือนี้ คุณสามารถมั่นใจได้ว่าแอปพลิเคชัน React ของคุณมีประสิทธิภาพ สามารถบำรุงรักษาได้ และสามารถขยายขนาดได้
ในขณะที่คุณเดินทางต่อไปกับ React การเชี่ยวชาญ createRef
จะพิสูจน์ให้เห็นว่าเป็นทักษะที่มีค่าในชุดเครื่องมือการพัฒนาของคุณอย่างไม่ต้องสงสัย ขอให้ทดลอง สำรวจกรณีการใช้งานต่างๆ และปรับปรุงความเข้าใจของคุณเกี่ยวกับคุณสมบัติที่จำเป็นของ React นี้ต่อไป