React Hooksでパフォーマンスを向上させる!状態更新関数のバッチ処理の仕組みと応用例
React Hooksにおける状態更新関数のバッチ処理について
バッチ処理の仕組み
- 状態更新関数が呼び出されると、React はその更新を スケジュール します。
- スケジュールされた更新は、コンポーネントのレンダリングが完了するまで キューに保持 されます。
バッチ処理の例
function MyComponent() {
const [count, setCount] = useState(0);
// ボタンをクリックすると、count が 1 ずつ増加します。
const handleClick = () => {
setCount(count + 1);
setCount(count + 1); // 2 回更新
};
return (
<div>
<p>カウント: {count}</p>
<button onClick={handleClick}>カウントアップ</button>
</div>
);
}
この例では、handleClick
関数は setCount
関数を 2 回呼び出します。しかし、React はこれらの更新をバッチ処理するため、コンポーネントは 1 回だけ再レンダリング されます。
バッチ処理が適用されない場合
以下の状況では、バッチ処理が適用されない可能性があります。
- 条件分岐によって実行される状態更新関数。
useEffect
フック内にある状態更新関数。- 異なるコンポーネントの状態を更新する関数。
import React, { useState } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1); // 最初の更新
setCount(count + 1); // 2番目の更新
};
return (
<div>
<p>カウント: {count}</p>
<button onClick={handleClick}>カウントアップ</button>
</div>
);
}
export default MyComponent;
説明
MyComponent
関数はuseState
フックを使用してcount
という状態変数を作成します。handleClick
関数はsetCount
関数を 2 回呼び出してcount
の値を 2 ずつ増加させます。- React はこれらの更新をバッチ処理するため、
MyComponent
コンポーネントは 1 回だけ再レンダリング されます。 - 再レンダリング後、
count
の値は 2 になります。
React Hooks で状態更新関数をバッチ処理する別の方法
useReducer フックを使用する
useReducer
フックは、状態の更新を管理するための別の方法を提供します。useReducer
は、useState
フックよりも複雑ですが、より多くの制御と柔軟性を提供します。useReducer
を使用すると、状態更新をバッチ処理するためにカスタム reducer 関数を作成できます。
import React, { useReducer } from 'react';
const initialState = { count: 0 };
const reducer = (state, action) => {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
default:
return state;
}
};
function MyComponent() {
const [state, dispatch] = useReducer(reducer, initialState);
const handleClick = () => {
dispatch({ type: 'increment' }); // バッチ処理される更新
dispatch({ type: 'increment' }); // バッチ処理される更新
};
return (
<div>
<p>カウント: {state.count}</p>
<button onClick={handleClick}>カウントアップ</button>
</div>
);
}
export default MyComponent;
この例では、useReducer
フックを使用して count
という状態変数を作成します。handleClick
関数は dispatch
関数を 2 回呼び出して count
の値を 2 ずつ増加させます。しかし、useReducer
はこれらの更新をバッチ処理するため、MyComponent
コンポーネントは 1 回だけ再レンダリング されます。
useEffect フックを使用する
useEffect
フックを使用して、状態更新を非同期に実行することもできます。これにより、バッチ処理が必要な更新をグループ化することができます。
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
setCount(count + 1); // バッチ処理される更新
setCount(count + 1); // バッチ処理される更新
}, []);
return (
<div>
<p>カウント: {count}</p>
</div>
);
}
export default MyComponent;
この例では、useEffect
フックを使用して、count
の値を 2 ずつ増加させる更新を実行します。useEffect
フックは空の依存関係配列を受け取るため、コンポーネントがマウントされたときに 1 回だけ 実行されます。これにより、2 つの更新がバッチ処理され、MyComponent
コンポーネントは 1 回だけ再レンダリング されます。
カスタムロジックを使用する
上記の方法で説明した方法に加えて、カスタムロジックを使用して状態更新をバッチ処理することもできます。これは、より複雑なユースケースの場合に役立ちます。
reactjs react-hooks