React 各hooksの覚え書き
Reactでは今やスタンダートになったhooksについて、公式APIとして提供されているものは色々あるが、今まではせいぜい useState
useEffect
程度しか使っていなかった。
最近徐々に他のhooksを使うシーンがあり、かなり便利だし、パフォーマンス観点でも使いこなせないとまずい気がして調べたのでまとめ。
公式のhooksは下記にまとまっている。 ja.reactjs.org
TL;DR
useState
はいわゆる state の保持・変更、複雑state管理なら、useReducer
を検討してもいいかもuseEffect
はレンダリング後に処理(副作用)したいときに利用、処理してからレンダリングしたいならuseLayoutEffect
※ただし使いすぎ注意useContext
はコンポーネント階層をまたぐバケツリレーの代替案、ただしコンポーネントが密結合になりかねないので設計に注意useCallback
useMemo
を利用することで不要な処理・レンダリングを抑制して高パフォーマンスを目指そうuseRef
はDOMアクセスの手段にとどまらず、インスタンス変数のイメージで書き換え可能な値の保持しておく使い方もできる
useState
多分最も基本的なhooksで特に使い方も難しくないので軽くメモ。
useState
はstateを保持するために使う。
const [count, setCount] = useState(0);
useStateの引数には初期値をセットして、戻り値として、stateとstateを変更する関数を得る。 state更新関数の引数に更新したい値をセットして利用。
ちなみに下記のように前のstateを元に更新もできる。
setCount(prevCount => prevCount - 1);
useState
は、Object.is
による比較ロジックが組み込まれていて、前回の値と同じ際はレンダリング等の実行を回避するようになっている
useEffect
useContext
主にバケツリレーの防止に約役立つ(バケツリレーは上位コンポーネントから下位コンポーネントへ値を渡していくこと、場合によっては何階層にも渡り辛みがある)
ただ、useContext
の利用は素直にpropsを受け取るような形で値を得ないので、上手くコンポーネント設計をしないと密結合になりやすいので乱用は避けた方が良さそう。
何となくだけど、アプリケーション全体に関連するstateを最上部で定義してどこからでもアクセスするように設計するとか、再利用の必要がなく、複雑、または多段でstateを管理するコンポーネント群に限定的に使う場合とかに使うとかの方が良い気がする。
また、useContext
を利用してグローバルstateライクに設計するパターンも見たことがある。
例として公式のコードを拝借
// 変数定義 const themes = { light: { foreground: "#000000", background: "#eeeeee" }, dark: { foreground: "#ffffff", background: "#222222" } }; // Contextを定義して、themes.lightを初期値に設定 const ThemeContext = React.createContext(themes.light); function App() { return ( {/* ThemeContext.Provider で子のコンポーネントでコンテクストを有効化, themes.dark をセット */} <ThemeContext.Provider value={themes.dark}> <Toolbar /> </ThemeContext.Provider> ); } function Toolbar(props) { return ( <div> <ThemedButton /> </div> ); } function ThemedButton() { // ThemeContext を読み込み const theme = useContext(ThemeContext); return ( {/* theme.backgound 等で値を読み込み */} <button style={{ background: theme.background, color: theme.foreground }}> I am styled by theme context! </button> ); }
useCallback
useMemo
詳細は別記事にまとめる予定なので軽く。
基本的にuseCallback
useMemo
はパフォーマンス改善のための hooks 。利用することで余計なレンダリングや再計算を抑制する。
Reactは何も気を付けずに構築すると、かなり再レンダリングや再計算が発生する。試しに自分のコンポーネントにlogを吐くようにしてみると、何回も同じlogが吐かれ、あれ?となるときがある。
自分の知っている限り理由はいくつかあるが、コンポーネントツリーの構築の仕方、stateの管理、propsでの値の受け渡し方等がある。
もちろんuseCallback
useMemo
で全てが解決できるわけではない。
useCallback
は、関数をメモ化して、依存配列が変更されたとき以外は再生成しない。
が、結構使い方に注意があり、どうやらReact.memo
と組み合わせて利用しないと効果を発揮しないらしい。
const memoizedCallback = useCallback( () => { doSomething(a, b); }, [a, b], );
useMemo
は、値をメモ化する。
何か値を計算して変数に入れることはよくあるが、Reactではコンポーネントの再レンダリングによって、変数の値も無駄に再計算されることがあるので、これを防止するために利用する。
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
useRef
ぶっちゃけあまり分かってない(使ったこと無い)
パッと見はDOMにアクセスするためのものだが、意外といろいろ使い方がありそう。 ここはもう少し調べて使ってみて理解が必要なので割愛。