「状態を持つ変数」と「更新する関数」を管理するReactフックです。
「状態を持つ変数」の値が変わると useState を宣言したコンポーネントで再レンダリングが起こります。
useStateの使い方
import { useState } from "react";
const [email, setEmail] = useState("");
// const [変数, 変数を更新するための関数(setter アクセサ)] = useState(状態の初期値);
// (例)変数 email / 更新する関数 setEmail() を宣言する
<input
type="email"
value={email}
onChange={e => setEmail(e.target.value)}
placeholder="Email..."
/>
const [member, setMember] = useState({ name: "", part: "" });
const [isLogined, setIsLogined] = useState<boolean>(true);
TypeScriptで
const [startDate, setStartDate] = useState(new Date());
の初期値を null にしたい場合は、以下のように記述します
const [startDate, setStartDate] = useState <Date|null>(null);
React HooksのuseEffectで関数コンポーネントにライフサイクルを持たせることができます
useEffectを使うと、useEffectに渡された関数はレンダーの結果が画面に反映された後に動作します。( = componentDidMount() )
また便利なことに、useStateフックはマウント解除にも使用できます。( =componentWillUnmount() )
useEffect の宣言方法
// 第1引数に「実行させたい副作用関数」を記述
// 第2引数に「副作用関数の実行タイミングを制御する依存データ」を記述
useEffect( 副作用関数, [依存する変数の配列])
初回レンダリング時とアンマウント時 のみ実行する
useEffect(() => {
console.log('useEffectが実行されました');
},[]);
// 第2引数の配列を空にして記述すると初回レンダリング時(とアンマウント時)のみ実行されます
第2引数を省略するとコンポーネントがレンダリングされるたび毎回実行されます。 (非常に危険です)
const [count, setCount] = useState(0);
useEffect(() => {
alert('変数 count が変更されましたよ');
}, [count]); // 第二引数の配列に任意の変数を指定
マウント解除時
const FunctionalComponent = () => {
React.useEffect(() => {
return () => {
console.log("Bye");
};
}, []);
return <h1>Bye, World</h1>;
};
https://zenn.dev/catnose99/scraps/30c623ba72d6b5
propsバケツリレーを使用することなく高い窓にまたがったコンポーネントで簡単にデータにアクセスするために使用します。
グローバルなステートを管理するのに使用する。 Redux とどちらを使うかについては設計段階で検討しましょう。
ReduxはMiddlewareを間に挟むことができるので、Middlewareを使いたい場合はReduxを使用します
useReducer で setState 関連のロジックを閉じ込める
deleteItem メソッドは、配列のうち該当する index の item を削除するメソッドであるが、こういったロジックをどこに書くかをかなり悩んできた。結論としては useReducer 内にロジックを保持するパターンが、一番疎結合である。
useReducerというAPIも登場しています。 useReducerはReduxにおけるReducerのような振る舞いをします。
useReducer が生きるのは、複数の関連したステート、つまりオブジェクトをステートとして扱うときです。
useReducerの使い方
import { useReducer } from "react";
const [state, dispatch] = useReducer(reducer, initialState);
[ステート, 発火関数 ] = useReducer(関数[, 初期値])
なお reducer は自作する必要があります。
const reducer = (state, action) => {
if(action === 'INCREMENT'){
return {count: state.count + 1}
}else{
return {count: state.count - 1}
}
}
Reduxと全く同じ使い方ですので、Reduxをさらっておくことをおすすめします。
useReducer は useState と似ている。
useState では「数値」、「文字列」、「論理値」を扱うことができるがそれを拡張して
useReducerでは「配列」、「オブジェクト」を扱えるようにする
React.memo / React.useMemo / React.useCallback は コンポーネントのレンダリング最適化や無限ループ防止を考えるときに登場します
useCallbackは関数そのものをメモ化します。
useMemoは関数の戻り値をメモ化します。
おもにファンクションの場合にuseCallbackを、
オブジェクトの場合にuseMemoを使用します。
Reactで再レンダリングが起きる条件
・stateが更新されたコンポーネントは再レンダリング
・propsが更新されたコンポーネントは再レンダリング
・再レンダリングされたコンポーネント配下の子コンポーネントは再レンダリングされる
コンポーネントをメモ化する
コンポジション(props.children)を使って子コンポーネントを渡す
memo() とは
使い方
MyChild.jsx
const MyChild = () => {
console.log('🤙 MyChildのレンダリングが開始されました');
return (
<div>MyChild</div>
);
}
export default MyChild;
↓ このように変更することでメモ化されます
MyChild.jsx
import { memo } from "react";
const MyChild = memo( () => {
console.log('🤙 MyChildのレンダリングが開始されました');
return (
<div>MyChild</div>
);
})
export default MyChild;
全体を memo() で囲っておきます。このようにすることで親コンポーネントに変更があった場合に MyChild は再レンダリングはされなくなります。
useMemo() とは
useMemoとは変数に対して memo化を行うものです。
useMemoは、以前行われた計算の結果をキャッシュし、useMemoが属するコンポーネントが再レンダリングしても、useMemoの第2引数(deps)が更新されていない場合は計算をスキップして以前の結果を使うという機能を提供します。
useCallback() とは
useEffect の高速化のための手法
useCallbackはパフォーマンス向上のためのフックで、メモ化したコールバック関数を返します。
useEffectと同じように、依存配列(=[deps] コールバック関数が依存している要素が格納された配列)の要素のいずれかが変化した場合のみ、メモ化した値を再計算します。
関数コンポーネントでは、Classコンポーネント時のref属性の代わりに、useRefを使って要素への参照を行います。
useStateを利用している場合はstateの変更される度にコンポーネントの再レンダリングが発生しますが、
useRefは値が変更になっても、コンポーネントの再レンダリングは発生しません。
コンポーネントの再レンダリングはしたくないけど、内部に保持している値だけを更新したい場合は、保持したい値をuseStateではなく、useRefを利用するのが良さそうです。
refを「ref」propとして渡さないでください。これはReactで予約されている属性名であり、エラーが発生します。
代わりに、forwardRefを使用します