今日はuseEffectフックを使って関数を実行するタイミングを操作します
useEffectフック
useEffect(() => {実行したい処理}, [state変数]);
このように書くとstate変数が変更されたタイミングで実行したい処理が実行されます
第2引数([state変数]のところ)を変えることでstate変数の変更タイミング以外でも処理を実行することができます
レンダリングごとに実行(Updating)
初期表示+再描画の度に実行したい場合は「useEffectの第2引数を省略」します
サンプルコードではWelcome.tsxで名前を入力、Enterボタンを押下するとメッセージと現在日時が表示されます
useEffectには現在日時を取得してセットする処理を書いています
components/Welcome.tsx
import {useState,useEffect} from 'react'; import {useName} from '../logic/useName'; function Welcome() { const {disp, changeName} = useName(); const [show, setShow] = useState(false); const [date, setDate] = useState(''); // useEffectの第2引数を省略すると描画ごとに実行される useEffect(() => { const now: string = new Date().toLocaleString(); setDate(now); }); return ( <div> <p>名前を入力してください</p> <input type="text" onBlur={e => changeName(e.target.value)}/> <button onClick={() => setShow(true)}>Enter</button> {show && <div> <p>ようこそ!! {disp}</p> <p>{date}</p> </div> } </div> ); } export default Welcome;
App.tsx
import Welcome from './components/Welcome'; function App() { return ( <div> <Welcome/> </div> ); } export default App;
logic/useName.tsx 入力された名前のsetter/getter
import {useState,useEffect} from 'react'; export const useName = () => { const [name, setName] = useState<string>('risa'); const [disp, setDisp] = useState<string>(name); useEffect(() => { setDisp(name + 'さん'); }, [name]); const changeName = (input:string) => { setName(input); }; return {disp, changeName}; }
再描画のタイミング「名前を変更してテキストボックスからフォーカスアウトした時」に現在日時も変わっています
初期表示のみ実行(Mounting)
初期表示のみ実行したい場合は「useEffectの第2引数を[]」にします
components/Welcome.tsx
import {useState,useEffect} from 'react'; import {useName} from '../logic/useName'; function Welcome() { const {disp, changeName} = useName(); const [show, setShow] = useState(false); const [date, setDate] = useState(''); // useEffectの第2引数を[](空配列)すると初期表示のみ実行される useEffect(() => { const now: string = new Date().toLocaleString(); setDate(now); }, []); return ( <div> <p>名前を入力してください</p> <input type="text" onBlur={e => changeName(e.target.value)}/> <button onClick={() => setShow(true)}>Enter</button> {show && <div> <p>ようこそ!! {disp}</p> <p>{date}</p> </div> } </div> ); } export default Welcome;
今度は名前を変更しても現在日時は変わっていません
コンポーネント破棄で実行(Unmounting)
コンポーネントが非表示になったタイミングで実行したい場合は「useEffectの第1引数に実行したい処理を記述」します
import {useState,useEffect} from 'react'; import {useName} from '../logic/useName'; function Welcome() { const {disp, changeName} = useName(); const [show, setShow] = useState(false); const [date, setDate] = useState(''); // useEffectの第1引数return句に記述した処理はコンポーネント破棄時に実行される useEffect(() => { const now: string = new Date().toLocaleString(); setDate(now); return () => console.log('コンポーネントが破棄されました'); }); return ( <div> <p>名前を入力してください</p> <input type="text" onBlur={e => changeName(e.target.value)}/> <button onClick={() => setShow(true)}>Enter</button> {show && <div> <p>ようこそ!! {disp}</p> <p>{date}</p> </div> } </div> ); } export default Welcome;
コードを修正後ホットリロード時にコンソールに「コンポーネントが破棄されました」と出力されました
第2引数を[]にするとマウント時とアンマウント時に実行されるようになるようです
コンポーネント破棄タイミングってブラウザ閉じた、別サイトへ移動って感じなのかな??
(非表示で破棄になるかと思って画像のbyeボタンを作ったが非表示では破棄されなかった)