ဒီ Post မှာ useRef Hook ကို ဘာအတွက်အသုံးပြုသလဲဆိုတာ ရှင်းပြချင်ပါတယ်။
useRef Hook ဟာ သူ့ရဲ့ argument (initialValue) ကို .current ဆိုတဲ့ သူ့ရဲ့ property မှာ initialized လုပ်ပြီး multable ref object ကို return ပြန်တဲ့ function တစ်ခုဖြစ်ပါတယ်။ သူ return ပြန်တဲ့ object ဟာ component ရဲ့ lifetime တစ်လျှောက်လုံးမှာ persist (ဆက်လက်တည်ရှိ) နေပါလိမ့်မည်။
const refContainer = useRef(initialValue);
;
useRef ကို အဓိက အသုံးပြုတဲ့ နေရာ (၂)ခုကို အောက်မှာ ဖော်ပြထားပါတယ်။
React ကို အသုံးပြုဖူးမယ်ဆိုရင် ဒီအတွက် useRef ကို အသုံးပြုတာတော့ ကျင့်သားရနေပါလိမ့်မည်။ useRef ကို class component မှာ အသုံးပြုပုံကို အောက်မ ှာ ဥပမာတစ်ခု ပေးထားပါတယ်။
import React, { Component, createRef } from "react"; class CustomTextInput extends Component { textInput = createRef(); focusTextInput = () => this.textInput.current.focus(); render() { return ( <> <input type="text" ref={this.textInput} /> <button onClick={this.focusTextInput}>Focus the text input</button> </> ); } }
;
Functional component အနေနဲ့ ရေးမယ်ဆိုရင်
import React, { useRef } from "react"; const CustomTextInput = () => { const textInput = useRef(); focusTextInput = () => textInput.current.focus(); return ( <> <input type="text" ref={textInput} /> <button onClick={focusTextInput}>Focus the text input</button> </> ); }
;
Functional component မှာ createRef အစား useRef အသုံးပြုတာကို မှတ်ထားပါ။
Functional component မှာ createRef ကို အသုံးပြုပြီး ref တစ်ခုကို create လုပ်မယ်ဆိုရင် React က အဲဒီ ref ရဲ့ instance ကို render အားလုံးကြားမှာ instance တစ်ခုတည်း create လုပ်နေမည့်အစား re-render လုပ်တိုင်းမှာ instance အသစ် တစ်ခုချင်းစီကို create လုပ်နေပါလိမ့်မည်။
(Funtional component မှာ createRef ကို မသုံးသင့်ပါ)
Class component နဲ့ functional component မှာ hook တွေကို အသုံးပြတဲ့အခါ re-render တွေကြား data တွေကို သိမ်းဆည်းနိုင်ဖို့ရန် နည်းလမ်း (၂)ခု ရှိပါတယ်။
Component state မှာ။ ။ state တွေ ပြောင်းလဲတဲ့အချိန်တိုင်း component ကို re-render လုပ်နေပါလိမ့်မည်။
Instance variable တစ်ခုမှာ။ ။ component ရဲ့ lifetime တစ်လျှောက်လုံးမှာ အဲဒီ variable က persist ဖြစ်နေပါလိမ့်မည်။ Instance variable တန်းဖိုးပြောင်း (update) သော်လည်း component ကို re-render လုပ်မှာ မဟုတ်ပါဘူး။
State variable မှာ (useState (သို့) useReducer)။ ။ state variable ပြောင ်းလဲရင် (update) ဖြစ်ရင် component ကို re-render ဖြစ်စေပါလိမ့်မည်။
ref မှာဆိုရင်။ ။class component ရဲ့ instance variable နဲ့ တူပါတယ်။ သူ့ရဲ့ .current property ကို value ပြောင်းပေမဲ့လည်း component တွေကို re-render ဖြစ်စေမှာ မဟုတ်ပါဘူး။
Mutable variable တစ်ခုကို ref မှာ သိမ်းတဲ့နည်းကို အောက်မှာ ဥပမာတစ်ခု ပေးထားပါတယ်။ <Timer> component က သူ re-render လုပ်တိုင်း setInterval ကို initialize လုပ်နေပါတယ်။ အဲဒီ interval ကို ရပ်တန့်စေဖို့ရန်အတွက် callback function တစ်ခုကို implement လုပ်ပေးဖို့ လိုအပ်ပါတယ်။
import React, { useRef, useEffect } from "react"; const Timer = () => { const intervalRef = useRef(); useEffect(() => { const id = setInterval(() => { console.log("A second has passed"); }, 1000); // component တစ်ခုလုံးကနေ ယူသုံး (accessible) နိုင်ဖို့အတွက် interval id လိုအပ်ပါတယ် // id ကို state variable ထဲမှာ သိမ်းထားမယ်ဆိုရင် component က re-render ပါလိမ့်မည်။ //state ကို update လုပ်တိုင်း interval အသစ်တစ်ခုကို create လုပ်မှာဖြစ်တဲ့အတွက် (re-render လုပ်တိုင်းလည်း ဒီလိုမျိုးဖြစ်) infinite loop hell ဖြစ်စေပါလိမ့်မည်။ intervalRef.current = id; return () => clearInterval(intervalRef.current); }); const handleCancel = () => clearInterval(intervalRef.current); return ( <> //… </> ); }
;
Lazy initialization မလုပ်ထားဘူးဆိုရင် component ကို rendering လုပ်နေချိန်မှာ ref ကို update မလုပ်သင့်ပါဘူး။ အဲဒီအစား ပုံမှန်အားဖြင့် ref တွေကို event handler တွေနဲ့ effects တွေမှာ ပြုပြင်မွမ်းမံ (modify) လုပ်သင့်ပါတယ်။ ဘာဖြစ်လို့လဲ? အဲဒါကို နားလည်ဖို့အတွက် React ရဲ့ component lifecycle ကို ပြန်ကြည့်ချင်ပါတယ်။
“Render phase” ကို React က restart လုပ်နိုင်တဲ့အတွက် အဲဒီအထဲမှာ ဘာမှမထားသင့်ပါဘူး။ Side effect မရှိပါဘူး။ Ref တစ်ခုရဲ့ value ပြောင်းခြင်း (update) လုပ်ခြင်းဟာ side effect တစ်ခုဖြစ်ပါတယ်။
import React, { useRef } from "react"; const RenderCounter = () => { const counter = useRef(0); // "Render phase" မှာ ref ရဲ့ value ကို update လုပ်မယ်ဆိုရင် // အဲဒီ value က တစ်ကြိမ်ထက်မက increment လုပ်နိုင်ပါတယ်။ counter.current = counter.current + 1; return ( <h1>{`The component has been re-rendered ${counter} times`}</h1> ); };
;
Side effect တွေအားလုံးကို “Layout phase” (သို့) “Commit phase” ထဲမှာ လုပ်သင့်ပါတယ်။ ဆိုလိုတာကတော့ React hook ကို အသုံးပြုမယ်ဆိုရင် useLayoutEffect (သို့) useEffect ထဲမှာ side effect တွေလုပ်တာကို ပြောချင်တာဖြစ်ပါတယ်။ အပေါ်က ဥပမာ ကို ဒီလိုမျိုးရေးသင့်ပါတယ်။
import React, { useRef } from "react"; const RenderCounter = () => { const counter = useRef(0); useEffect(() => { // component ကို re-render လုပ်ပြီးတဲ့အချိန်တိုင်း counter က increase လုပ်နေပါလိမ့်မည်။ counter.current = counter.current + 1; }); return ( <h1>{`The component has been re-rendered ${counter} times`}</h1> ); };
;
useRef Hook က functional component တွေထဲမှာ mutable variable တွေကို create လုပ်နိုင်စေပါတယ်။ useRef Hook ကို အသုံးပြုတဲ့အခါ မှတ်ထားရမယ့် အဓိကအချက် (၃) ချက်ရှိပါတယ်။
useRef နဲ့ create လုပ်ထားတဲ့ ref တစ်ခုဟာ component mounted ဖြစ်တဲ့အချိန်မှာပဲ created ဖြစ်နေပါလိမ့်မည်။ ပြီးတော့ component ရဲ့ lifetime တစ်လျှောက်လုံးမှာ အဲဒီ ref ကို သိမ်းဆည်း (preserve) ထားပါလိမ့်မည်။
Ref ကို DOM nodes (သို့) React elements တွေကို access လုပ်ဖို့ အသုံးပြုလို့ရပါတယ်။ ပြီးတော့ class component ရဲ့ instance variable လိုမျိုး mutable variable တွေကို သိမ်းဆည်း (store) နိုင်ဖို့ရန် အသုံးပြုပါတယ်။
Ref တစ်ခုကို တန်ဖိုးပြောင်း (update) တာက side effect တစ်ခုဖြစ်တဲ့အတွက် useEffect (သို့) useLayoutEffect (သို့) event handler တွေထဲမှာပဲ ref ကို update လုပ်သင့်ပါတယ်။