ライフサイクルとは?
コンポーネントがマウント(描画)されてからアンマウント(破棄)されるまでの過程のことです。
フェーズ
マウント
更新(マウントしたコンポーネントを更新)
アンマウント
フックのルール
コンポーネント外でフックを呼び出してはいけない。
フック(Hook)とは?
関数コンポーネントで利用できる関数のことです。
メリット
- コンポーネント内で重複するロジックをフックとして切り出すことで複数コンポーネントで共通利用できる。
- コンポーネントから複雑なロジックをフックとして切り出せばコードの見通しがよくなる。
- 状態管理やコールバックを簡潔に記述できる。
カスタムフック
自作のフックのことです。基本的にカスタムフック内で関数を定義する場合は、useCallbackを使うことが推奨されます。いろんなプロジェクトで使うことが想定されるので。
組み込まれたフック
useState
stateとstateを定義や更新する関数を返すフックです。これを使えば関数コンポーネント内でstate管理(値の保持)を行うことができます。
構文
1 |
const [State変数,State更新関数] = useState(State変数の初期値); |
state更新関数の名前は大抵の場合は「setXXX」という名前が付けられることが多いです。
実装例
クリックしたらカウントアップされるTestというコンポーネントの例
1 2 3 4 5 6 7 |
const { useState } = React;(import React,{useState} from 'react';) const [count,setCount] = useState(0); function Test(){ const [count,setCount] = useState(0); return <h1 onClick={()=>setCount(count + 1)}>Num:{count}</h1>; } |
下記のようにすればState更新関数にコールバック関数(c => c)も渡すことは可能です。関数で渡した「c」には現在のcountの値が格納されます。コールバック関数の戻り値が次のステート内容になります。
1 2 3 4 5 |
const { useState } = React; function Test(){ const [count,setCount] = useState(0); return <h1 onClick={()=>setCount( c => c + 1)}>Count:{count}</h1>; } |
useReducer
useStateと同じように、複数の関連したステート、つまりオブジェクトの状態を保持する際に使うと良いです。
useStateとの違い、メリット
例えば、APIを実行して処理結果を更新する際などは、useStateだとonClickにロジックが寄ってしまいがちになりますが、useReducerを使うことで外部化することが可能になります。
また、テストコードを記述する際にロジックと疎結合になり、コンポーネントのテストを書くのが楽になります。(Reducerは状態を持たない関数なのでテストコードを書くのが簡単になります。)
useEffect
コンポーネントに副作用を追加するフックです。副作用とは次のような処理を実行する関数のこと。コンポーネントのマウント後に指定した副作用を実行することが可能です。
- DOMの変更
- APIとの通信
- 非同期処理
- console.log
動作タイミング
レンダリングの後です。従来のクラスコンポーネントでいうところの「componentDidMount()」の動作によく似ています。
構文
第一引数に副作用(関数など)を渡せばコンポーネントのマウント後にそれが実行されます。
1 |
useEffect(副作用,[変数]); |
第二引数には変化を検知する対象の変数を指定します。(その変化のみでしか実行されないようにできます。)なお、第二引数に空の配列を渡すことでマウント後1度のみuseEffectを実行させるといったことが可能です。
実装例
useEffectにDOMを描画する関数を渡してマウント後に再描画を何度も行わせることができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import React,{useState,useEffect} from'react'; function App() { const [count,setCount] = useState(0); useEffect(()=>{ document.getElementById('effect').innerText=`あなたは ${count}回クリックしました。`; }); return( <div><p id="effect"></p> <button onClick={()=>setCount(count+1)}>click</button></div> ); } |
useMemo/useCallback
コンポーネントレンダリングのパフォーマンスの向上に使えます。少しややこしいので下記の記事で解説しています。
【React】「useMemo/useCallback」について
useContext
Reactのhookの一つです。コンポーネント間のステートの共有ができます。
コンテキストオブジェクト(React.createContextの戻り値)からコンテキストの値を取得するフックです。Propsを利用しなくてもコンポーネントにデータを渡せます。
Contextオブジェクト
親子関係にない離れたコンポーネント間で共有するためのパーツです。Contextオブジェクトには「Context Provider」と「Context Consumer」の2種類のコンポーネントがあります。
Context Provider
ツリーのトップに指定することでContextを参照できる範囲を限定するために使用します。
Context Consumer
Contextの値を利用したい場所で使用します。なお、React Hookの「useContext」はConsumerの代替になります。
useStateやuseReducerとの違い
useStateやuseReducerでもステートの共有はすることができるかと思います。違いとしてはpropsでのバケツリレーが発生しない点です。
用途
下記のようなサイトを通じて汎用性のある情報を共有したい場合などに使えます。
- 認証状態
- レイアウトのデザイン情報
実装例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
import React,{useState,useContext,createContext} from'react'; const MyContext = createContext(); function App() { const [count,setCount] = useState(0); const value = { name:'soarflat', handleClick:()=>setCount(count=>count+1)}; return( <div> <p>count:{count}</p> <MyContext.Provider value={value}> <ChildComponent/> </MyContext.Provider> </div> ); } function ChildComponent(){ return <GrandChildComponent/>; } function GrandChildComponent(){ const context = useContext(MyContext); return( <> <p>{context.name}</p> <button onClick={context.handleClick}>increment</button> </> ); } export default App; |
propsのバケツリレーをすることなくコンポーネント間で値を渡すことができています。
useRef
refオブジェクト(React.createRefの戻り値)を返すフックです。refオブジェクトを利用することでDOMの参照やコンポーネント内で前回のstateを保持することが可能です。
構文
refオブジェクトを生成できます。refオブジェクトをHTMLのref属性に指定することでDOMを参照することができるようになります。
1 2 3 4 |
useRef(値) const 変数 = useRef(値); 変数.current //useRefで指定した値を参照できます。 |
実装例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import React,{useRef} from'react'; function App(){ const useref = useRef(null); const onButtonClick=()=>{ if(!useref.current) return; useref.current.focus(); }; return( <> <input ref={useref} type="text"/> <button onClick={onButtonClick}>input要素をフォーカスする</button> </> ); } export default App; |
この記事へのコメントはありません。