React useEffect() のクリーンアップ:空の依存関係配列、useRef、useMemo、useCallback の使い分け
React Hooks useEffect() のクリーンアップについて
React Hooks の useEffect
は、コンポーネントのレンダリング後に副作用を実行する強力なツールです。しかし、コンポーネントがアンマウントされるときに、副作用をクリーンアップする必要もあります。
useEffect のクリーンアップ
useEffect
は、オプションの2番目の引数を受け取ります。これは、副作用をクリーンアップするために実行される関数です。この関数は、コンポーネントがアンマウントされるたびに呼び出されます。
例
以下の例では、useEffect
を使用してイベントリスナーを追加し、コンポーネントがアンマウントされるときに削除します。
const MyComponent = () => {
useEffect(() => {
window.addEventListener('click', () => {
console.log('Click!');
});
return () => {
window.removeEventListener('click', () => {
console.log('Click!');
});
};
}, []);
return <div>My Component</div>;
};
useEffect のクリーンアップを componentWillUnmount のみに使用
useEffect
のクリーンアップは、コンポーネントがアンマウントされるたびに実行されます。しかし、componentWillUnmount
のようなライフサイクルメソッドは、コンポーネントがアンマウントされる直前にのみ実行されます。
空の依存関係配列を使用する
useEffect
に空の依存関係配列を渡すと、副作用はレンダリング後に一度だけ実行され、コンポーネントがアンマウントされるときにクリーンアップされます。
const MyComponent = () => {
useEffect(() => {
// 副作用
return () => {
// クリーンアップ
};
}, []);
return <div>My Component</div>;
};
useRef
を使用して、useEffect
内で参照を保持することができます。この参照を使用して、クリーンアップ関数内で副作用をキャンセルすることができます。
const MyComponent = () => {
const ref = useRef(null);
useEffect(() => {
ref.current = setInterval(() => {
console.log('Tick!');
}, 1000);
return () => {
clearInterval(ref.current);
};
}, []);
return <div>My Component</div>;
};
useEffect
のクリーンアップは、コンポーネントがアンマウントされるときに副作用をクリーンアップするのに役立ちます。空の依存関係配列を使用するか、useRef
を使用することで、useEffect
のクリーンアップを componentWillUnmount
のみに使用することができます。
const MyComponent = () => {
useEffect(() => {
console.log('useEffect 副作用');
return () => {
console.log('useEffect クリーンアップ');
};
}, []);
return <div>My Component</div>;
};
useRef を使用する
const MyComponent = () => {
const ref = useRef(null);
useEffect(() => {
ref.current = setInterval(() => {
console.log('Tick!');
}, 1000);
return () => {
clearInterval(ref.current);
};
}, []);
return <div>My Component</div>;
};
componentWillUnmount を使用する
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0,
};
}
componentDidMount() {
this.interval = setInterval(() => {
this.setState({ count: this.state.count + 1 });
}, 1000);
}
componentWillUnmount() {
clearInterval(this.interval);
}
render() {
return (
<div>
Count: {this.state.count}
</div>
);
}
}
このコードでは、componentWillUnmount
ライフサイクルメソッドを使用して、setInterval
をキャンセルしています。
const MyComponent = () => {
const [count, setCount] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setCount(count => count + 1);
}, 1000);
return () => {
clearInterval(interval);
};
}, []);
useEffect(() => {
return () => {
console.log('useEffect クリーンアップ');
};
}, []);
return (
<div>
Count: {count}
</div>
);
};
このコードでは、useEffect
と componentWillUnmount
を組み合わせて使用しています。1つ目の useEffect
は setInterval
を設定し、2つ目の useEffect
はコンポーネントがアンマウントされるときに実行されます。
useEffect のクリーンアップを行う他の方法
クラスベースのコンポーネントを使用している場合は、componentWillUnmount
ライフサイクルメソッドを使用して副作用をクリーンアップすることができます。
useMemo
を使用して、副作用を実行するために必要な値をメモ化することができます。これにより、副作用が実行される頻度を減らすことができ、パフォーマンスを向上させることができます。
第三者ライブラリを使用する
react-cleanup
などの第三者ライブラリを使用して、useEffect
のクリーンアップを簡略化することができます。
- シンプルな副作用の場合は、空の依存関係配列を使用するのが最善の方法です。
- より複雑な副作用の場合は、
useRef
またはcomponentWillUnmount
を使用する必要があります。 - パフォーマンスが重要な場合は、
useMemo
またはuseCallback
を使用する必要があります。 - 第三者ライブラリは、コードを簡略化したい場合に役立ちます。
useEffect
のクリーンアップを行うには、さまざまな方法があります。どの方法を使用するべきかは、状況によって異なります。
reactjs react-hooks