React useEffectフックとサードパーティライブラリ:複雑なアプリケーションにおける副作用処理の管理
ReactにおけるuseEffectの使い分け:わかりやすい解説
useEffect
フックは、以下の2つの主要な場面で使用されます。
マウント時とアンマウント時の処理
- 例:イベントリスナーの解除、購読解除
- クリーンアップ関数を使用して、アンマウント時に不要になった処理を解除できます。
- 例:データフェッチ、イベントリスナーの登録
- コンポーネントがDOMにマウントされるときに実行される処理を記述できます。
状態やプロップスの更新に応じて実行される処理
- 依存関係配列を使用して、特定の値の変更のみに反応するように設定できます。
- 例:フォーム入力値の検証、アニメーションの実行
- コンポーネントの状態やプロップスが更新されたときに実行される処理を記述できます。
使い分けるポイント
- 複数の処理を実行する場合は、複数の
useEffect
フックを使用します。 - 状態・プロップスの更新に応じて処理を実行する場合は、依存関係配列に更新対象の値を指定します。
- マウント時・アンマウント時の処理のみの場合は、依存関係配列を空配列にします。
例
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
const [data, setData] = useState([]);
// マウント時にデータフェッチ
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => setData(json));
}, []);
// ボタンクリック時にカウントアップ
const handleIncrement = () => {
setCount(count + 1);
};
// カウントが更新されたらログ出力
useEffect(() => {
console.log(`カウントが更新されました: ${count}`);
}, [count]);
return (
<div>
<p>カウント:{count}</p>
<button onClick={handleIncrement}>カウントアップ</button>
<p>データ:{data.title}</p>
</div>
);
}
この例では、useEffect
フックを2つ使用しています。
1つ目は、マウント時にfetch
APIを使用してデータフェッチを実行しています。依存関係配列が空なので、マウント時のみ実行されます。
2つ目は、count
ステートが更新されたときにログを出力しています。依存関係配列にcount
を指定しているので、count
が更新されるたびに実行されます。
マウント時にデータフェッチ
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [data, setData] = useState([]);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => setData(json));
}, []);
return (
<div>
<p>データ:{data.title}</p>
</div>
);
}
この例では、コンポーネントがマウントされるときにfetch
APIを使用してデータフェッチし、data
ステートに格納しています。依存関係配列が空なので、マウント時のみ実行されます。
ボタンクリック時にアラートを表示
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [show, setShow] = useState(false);
useEffect(() => {
if (show) {
alert('ボタンがクリックされました!');
}
}, [show]);
const handleClick = () => {
setShow(true);
};
return (
<div>
<button onClick={handleClick}>ボタン</button>
</div>
);
}
この例では、ボタンをクリックするとshow
ステートがtrue
になり、useEffect
フックが実行されます。依存関係配列にshow
を指定しているので、show
がtrue
になったときのみアラートが表示されます。
タイマーの実装
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setCount(count + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
return (
<div>
<p>カウント:{count}</p>
</div>
);
}
この例では、useEffect
フックを使用して1秒ごとにカウントをインクリメントするタイマーを実装しています。依存関係配列が空なので、マウント時のみタイマーが開始されます。
DOM操作の実行
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [color, setColor] = useState('red');
useEffect(() => {
document.body.style.backgroundColor = color;
}, [color]);
const handleChange = (event) => {
setColor(event.target.value);
};
return (
<div>
<select value={color} onChange={handleChange}>
<option value="red">赤</option>
<option value="green">緑</option>
<option value="blue">青</option>
</select>
</div>
);
}
この例では、ドロップダウンメニューから色を選択すると、useEffect
フックを使用してドキュメントの背景色を変更します。依存関係配列にcolor
を指定しているので、color
が変更されるたびに背景色が更新されます。
サブスクリプションの設定
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
const subscription = eventEmitter.on('count-updated', (newCount) => {
setCount(newCount);
});
return () => subscription.unsubscribe();
}, []);
return (
<div>
<p>カウント:{count}</p>
</div>
);
}
この例では、useEffect
フックを使用してeventEmitter
からのイベントを購読し、カウントを更新しています。依存関係配列が空なので、マウント時に購読が開始されます。
ReactにおけるuseEffect
以外の代替手段
状態更新関数
- 例:フォーム入力値の更新、ボタンのクリック状態の管理
useState
フックと組み合わせて使用します。- シンプルなデータ更新やDOM操作に適しています。
import React, { useState } from 'react';
function MyComponent() {
const [name, setName] = useState('');
const handleChange = (event) => {
setName(event.target.value);
};
return (
<div>
<input type="text" value={name} onChange={handleChange} />
<p>名前:{name}</p>
</div>
);
}
コンポーネントのライフサイクルメソッド
- 例:データフェッチ(
componentDidMount
)、イベントリスナーの登録(componentDidMount
)、購読解除(componentWillUnmount
) - クラスコンポーネントでのみ使用できます。
- マウント、アンマウント、更新などのコンポーネントのライフサイクルイベントに対応する処理に適しています。
import React, { Component } from 'react';
class MyComponent extends Component {
componentDidMount() {
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => this.setState({ data: json }));
}
componentWillUnmount() {
// イベントリスナーの解除など
}
render() {
const { data } = this.state;
return (
<div>
<p>データ:{data.title}</p>
</div>
);
}
}
カスタムフック
- 例:データフェッチロジック、アニメーションロジック
useState
やuseEffect
などの他のフックを組み合わせることができます。
import React, { useState, useEffect } from 'react';
function useFetchData(url) {
const [data, setData] = useState([]);
useEffect(() => {
fetch(url)
.then(response => response.json())
.then(json => setData(json));
}, [url]);
return data;
}
function MyComponent() {
const data = useFetchData('https://jsonplaceholder.typicode.com/todos/1');
return (
<div>
<p>データ:{data.title}</p>
</div>
);
}
サードパーティライブラリ
react-router
などのルーティングライブラリは、ページ遷移に伴う副作用処理を管理するのに役立ちます。redux
やmobx
などの状態管理ライブラリは、複雑なアプリケーションにおける状態管理に役立ちます。
選択の指針
- 状態管理やルーティングなど、特定のユースケースには、サードパーティライブラリが適しています。
- 複雑な処理や再利用可能な処理には、カスタムフックが適しています。
- シンプルな処理には、状態更新関数やコンポーネントのライフサイクルメソッドが適しています。
reactjs