1.はじめに
曖昧な理解のため、自分が見返すためのメモ書きのような感覚でまとめていきます。
少しでも参考になれば幸いです。
2.useContext
useContextとは
useContext はコンポーネントでコンテクスト (Context) の読み取りとサブスクライブ(subscribe, 変更の受け取り)を行うための React フックです。
特徴
- コンポーネント間でデータを共有するためのフック
- ネストの深いコンポーネントにもデータを渡せる(Prop Drilling 解消)
- Provider を使って値を渡し、useContext で取得。
使用方法
-
const 変数名 = createContext(値);
の形でcontextを設定する- 今回はカウントする処理を例に記載しております
import { createContext } from "react";
// Contextの型を定義
interface CounterContextType {
count: number;
increment: () => void;
decrement: () => void;
reset: () => void;
}
// Contextを作成(初期値は `undefined` にしてエラーハンドリングを行う)
const CounterContext = createContext<CounterContextType | undefined>(undefined);
export default CounterContext;
- providerを作成する。
import React, { useState } from "react";
import CounterContext from "./CounterContext";
// Propsの型を定義
interface CounterProviderProps {
children: React.ReactNode;
}
const CounterProvider: React.FC<CounterProviderProps> = ({ children }) => {
const [count, setCount] = useState<number>(0);
// カウントを増やす
const increment = () => setCount((prev) => prev + 1);
// カウントを減らす
const decrement = () => setCount((prev) => prev - 1);
// カウントをリセット
const reset = () => setCount(0);
return (
<CounterContext.Provider value={{ count, increment, decrement, reset }}>
{children}
</CounterContext.Provider>
);
};
export default CounterProvider;
- usecontextを使ってデータを取得
import React, { useContext } from "react";
import CounterContext from "./CounterContext";
const CounterDisplay: React.FC = () => {
const context = useContext(CounterContext);
// Contextがない場合のエラーハンドリング
if (!context) {
throw new Error("CounterDisplay must be used within a CounterProvider");
}
const { count, increment, decrement, reset } = context;
return (
<div style={{ textAlign: "center", padding: "20px" }}>
<h1>カウント: {count}</h1>
<button onClick={increment}>増やす +</button>
<button onClick={decrement}>減らす -</button>
<button onClick={reset}>リセット</button>
</div>
);
};
export default CounterDisplay;
- App.tsxにproviderを指定する
import React from "react";
import ReactDOM from "react-dom";
import CounterProvider from "./CounterProvider";
import CounterDisplay from "./CounterDisplay";
const App: React.FC = () => {
return (
<CounterProvider>
<CounterDisplay />
</CounterProvider>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
実際の動作
参考
usecontextだけだと状態管理が複雑になるので、大規模開発の場合はReduxやRecoilを使用するのがよい。
3.useMemo
useMemoとは
useMemo は、レンダー間で計算結果をキャッシュするための React フックです。
特徴
- 計算コストの高い処理をメモ化(キャッシュ)し、不要な再計算を防ぐ
- 値を返す(関数ではなく計算結果をキャッシュする)
- 依存配列の値が変わったときだけ再計算される
使用方法
基本構文は以下
第一引数:更新がかかった際に実行したい処理を記載する(計算処理, stateの更新 etc...)
第二引数:依存配列で、指定の値に更新がかかった時のみ処理が走る
const memoizedValue = useMemo(() => abを更新する処理等, [a, b]);
実際の動作
- stateのnumを2乗した値をmemoに保存する処理
参考
useEffectとの使い分け
フック | 目的 | 実行タイミング | 返すもの |
---|---|---|---|
useMemo | 計算結果をキャッシュ | レンダリング中 に実行 | 値(計算結果) |
useEffect | 副作用処理(API通信・DOM操作) | レンダリング後 に実行 | 関数(クリーンアップ処理) |
4.useRef
useRefとは
useRef は、レンダー時には不要な値を参照するための React フックです。
特徴
- DOM 要素へのアクセスを管理
- 再レンダリングを発生させずに値を保持
- current プロパティを持ち、値を更新できる
- コンポーネントが再レンダリングされても、値がリセットされない
使用方法
基本構文
-
initialValue
(初期値)は null や undefined、数値、オブジェクトなど -
ref.current
で 値にアクセス可能 - 値を変更しても再レンダリングは発生しない
const ref = useRef(initialValue);
実際の動作
- アニメーションを変更する処理
- このパターンで、usestateを使用してしまうと不要な再レンダリングが走ってしまう
- コンポーネントが再度更新される
- アニメーションや UI 更新を最適化したい場合にuserefはより良い選択肢
- ボタンを押しても、React は無駄な再描画をしない
- 状態管理をstateで行う必要がない
- このパターンで、usestateを使用してしまうと不要な再レンダリングが走ってしまう