Hook တွေကို React version 16.8 မှာ ထည့်သွင်းထားတဲ့ feature အသစ် ဖြစ်ပါတယ်။ သူတို့က class ဆောက်ပေးစရာမလိုဘဲ state တွေနှင့် React ရဲ့ အခြားသော feature တွေကို သုံးလို့ရအောင် ကူညီပေးပါတယ်။ သူတို့ကို အဓိက functional component မှာ state နဲ့ side effect တွေကို ကိုင်တွယ်ဖို့ (handle) ရန်အတွက် အသုံးပြုပါတယ်။ React Hook တွေအားဖြင့် stateful fuction တွေကို functional component ထဲမှာ သုံးလို့ရပါတယ်။ Hook တွေကို class တွေထဲမှာ သုံးလို့မရပါဘူး။
ပထမ အကြောင်းပြချက်တစ်ခုကတော့ functional component ထဲမှာ state တွေကို သုံးလို့ရတဲ့အတွက်ကြောင့်ပါ။ တကယ်တမ်းဆိုရင် state တွေကို function တွေထဲမှာ သုံးလို့မရပါဘူး။ ဒါပေမဲ့ ဒီ Hook တွေကို အသုံးပြုခြင်းအားဖြင့် state တွေကို function တွေထဲမှာ သုံးလို့ရပါတယ်။ နောက်ထပ် အကြောင်းပြချက်တစ်ခုကတော့ side effect တွေကို react component ထဲမှာ ကိုင်တွယ် (handle) တဲ့အရာပါပဲ။ ဘာကိုပြောချင်တာလဲဆိုရင် useEffect လိုမျိုး Hook တွေကို ပြောချင်တာဖြစ်ပါတယ်။
ဥပမာ class နဲ့ရေးမယ်ဆိုရင်
class FriendStatusWithCounter extends React.Component { constructor(props) { super(props); this.state = { count: 0, isOnline: null }; this.handleStatusChange = this.handleStatusChange.bind(this); } componentDidMount() { document.title = `You clicked ${this.state.count} times`; ChatAPI.subscribeToFriendStatus( this.props.friend.id, this.handleStatusChange ); } componentDidUpdate() { document.title = `You clicked ${this.state.count} times`; } componentWillUnmount() { ChatAPI.unsubscribeFromFriendStatus( this.props.friend.id, this.handleStatusChange ); } handleStatusChange(status) { this.setState({ isOnline: status.isOnline }); } render() { if (this.state.isOnline === null) { return ‘Loading…’; } return this.state.isOnline ? ‘Online’ : ‘Offline’; } }
;
Hook တွေကို အသုံးပြုပြီးရေးမယ်ဆိုရင် useEffect Hook ဟာ componentDidMount, componentDidUpdate နဲ့ componentWillUnmount ဒီသုံးခု ပေါင်းစပ်ထားတဲ့အရာဖြစ်တယ်လို့ မှတ်ထားလို့ရပါတယ်။
Default အနေနဲ့ component ပထမဆုံး render လုပ်တဲ့ချိန်နှင့် update လုပ်တဲ့အချိန်တိုင်းမှာ useEffect ကို run ပါတယ်။ Subscription တွေကို ထည့်(add) ဖို့ နှင့် ဖျက်(remove) ဖို့အတွက် function (arrow function) တစ်ခုကို return လုပ်လို့ရပါတယ်။
State တွေကို ဒီလိုဆောက်ရပါတယ်။
const [count, setCount] = useState(0);
;
const [count, setCount] : လက်ရှိ(current) count ဆိုတဲ့ state နှင့် အဲဒီ state ကို update လုပ်တဲ့ setCount ဆိုတဲ့ function
useState(0) : state ရဲ့ မူလတန်ဖိုး (initial value) ကို သတ်မှတ်။
import React, { useState, useEffect } from ‘react’; function FriendStatusWithCounter(props) { const [count, setCount] = useState(0); useEffect(() => { document.title = `You clicked ${count} times`; }); const [isOnline, setIsOnline] = useState(null); useEffect(() => { function handleStatusChange(status){ setIsOnline(status.isOnline); } ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); if (isOnline === null) { return ‘Loading…’; } return isOnline ? ‘Online’ : ‘Offline’; }
;
Hook ထဲက componentDidUpdate(prevProps, prevState) တစ်ချို့ကိစ္စတွေမှာ component render လုပ်တိုင်း useEffect က run နေမယ်ဆိုရင် performance ကျစေနိုင်ပါတယ်။ Class component မှာဆိုရင် componentDidUpdate function ထဲမှာ prevProps (သို့) prevState ကို နှိုင်းယှဉ်ပေးခြင်းအားဖြင့် ဖြေရှင်းလို့ပါတယ်။
componentDidUpdate(prevProps, prevState) { if (prevState.count !== this.state.count) { document.title = `You clicked ${this.state.count} times`; } }
;
Functional component တွေမှာ ဒီလိုလုပ်ဖို့အတွက် useEffect ဆိုတဲ့ Hook API ပါပြီးသားဖြစ်ပါတယ်။ State တစ်ခုခုရဲ့ တန်ဖိုးပြောင်းလဲသွားတဲ့အချိန်တိုင်း effect ကို run တာမဟုတ်ဘဲ ကိုယ်သတ်မှတ်ထားတဲ့ဟာ state ရဲ့တန်ဖိုး ပြောင်းလဲသွားမှပဲ effect ကို run စေချင်ရင်လည်းရပါတယ်။ အဲဒီလိုလုပ်ဖို့အတွက် useEffect ရဲ့ ဒုတိယ argument မှာ array တစ်ခုကို ထည့်ထားပေးရပါတယ်။
useEffect(() => { document.title = `You clicked ${count} times`; }, [count]); // count ရဲ့ တန်ဖိုးပြောင်းမှ effect ကို ပြန် run ပါလိမ့်မည်
;
Top Level မှာပဲ Hook တွေကို ခေါ် (call) ပါ။
Loop တွေ, condition တွေ, nested function တွေမှာ Hook တွေကို မခေါ်သင့်ပါဘူး။ အဲဒီအစား React function ရဲ့ top level မှာပဲ Hook တွေကို ခေါ်သုံးပါ။ ဒီလိုလုပ်ခြင်းအားဖြင့် Hook တွေက နည်းစနစ်မှန်ကန်စွာ အလုပ်လုပ်ပါလိမ့်မည်။ useState နဲ့ useEffect တွေ အများကြီးခေါ်ထားပေမဲ့လည်း state တွေကို React က မှန်ကန်စွာ ထိန်းသိမ်း (preserve) ပေးပါလိမ့်မည်။
React fuction တွေ ကနေပဲ Hook တွေကို ခေါ်ပါ။
ပုံမှန် (regular) Javascript function တွေကနေလည်း Hook တွေကို မခေါ်သင့်ပါဘူး။
ကိုယ်တိုင်လုပ်ထားတဲ့ Hook (custom hook) တွေကနေလည်း ခေါ်လို့ရပါတယ်။
ဒီအရာတွေကို မှတ်ထားပါ
Component unmount လုပ်တဲ့အချိန်မှာ interval ကို ရှင်းထုတ် (clear) လုပ်ချင်တယ်ဆိုရင် ဘယ်လိုလုပ်ရမလဲ။ Class component မှာဆိုရင် life-cycle method တစ်ခုဖြစ်တဲ့ componentWillUnmount ထဲမှာ ရှင်းထုတ်တဲ့အလုပ် လုပ်ရမှာဖြစ်ပါတယ်။ ဒါပေမဲ့ Hook မှာဆိုရင် useEffect ထဲမှာ ရိုးရှင်းစွာလုပ်နိုင်ပါတယ်။
Return function ထဲမှာ interval ကို ရှင်းထုတ်ရမှာ ဖြစ်ပါတယ်။ ဆိုတော့ component unmount ဖြစ်တဲ့အချိန်မှာ interval က ရှင်းထုတ်ပြီးသားဖြစ်နေပါလိမ့်မည်။
ဒါပေမဲ့ state ပြောင်းလဲ (update) တဲ့အချိန်တိုင်း ဒီ hook method က run နေပါလိမ့်မည်။ ဒါပေမဲ့ ဒီ method ကို component mount လုပ်တဲ့အချိန်နှင့် component unmount လုပ်တဲ့အချိန်မှာပဲ run စေချင်တယ်ဆိုရင် ဘယ်လိုလုပ်ရမလဲ?
ရိုးရိုးရှင်းရှင်းလေးပါပဲ။ useEffect ရဲ့ ဒုတိယ argument မှာ array အလွတ် (empty array) ကို ထည့် (pass လုပ်) ထားပေးမယ်ဆိုရင် component mount လုပ်တဲ့အချိန်နှင့် component unmount လုပ်တဲ့အချိန်မှာပဲ အဲဒီ method ကို run နေပါလိမ့်မည်။
သတ်မှတ်ထားတဲ့ state တွေမှာပဲ ဒီ side effect ကို run စေချင်တယ်ဆိုရင် ဘယ်လိုလုပ်ရမလဲ? မူလတန်ဖိုး (initial value) false ရှိတဲ့ isStarted ဆိုတဲ့ state တစ်ခုရှိတယ်ဆိုကြပါစို့။ isStarted state ရဲ့တ န်ဖိုးက true ဖြစ်မှပဲ useEffect ကို run စေချင်တယ်ဆိုရင် array အလွတ်တစ်ခုကို ထည့်ပေးမယ့်အစား အဲဒီ array ထဲမှာ isStarted ဆိုတဲ့ state ကို ထည့်ထားပေးရပါမယ်။