ReactのEffect Hookと組み合わせてコンポーネントの副作用のクリアを分析する
4791 ワード
友達のオンラインコンポーネントを購読する
私たちはDidMountの時にIDで友達のオンライン状態を購読し、メモリの漏洩を防ぐためにWillUnmountで購読をクリアする必要があります.
しかし、コンポーネントが画面に表示されたときにfriend propが変化したときに何が起こるのでしょうか.私たちのコンポーネントは、元の友達の状態を引き続き示します.これはバグです.また、購読をキャンセルする際に誤った友人IDを使用したため、メモリが漏洩したりクラッシュしたりする問題もあります.
友達のオンライン購読コンポーネントの最適化
Props更新によるバグを解決するには、DidUpdateで修正購読を行う必要があります.
Effect Hook
useEffect()は、関数コンポーネントでの副作用操作をデフォルトで実行することができます.これは、最初のレンダリング後と更新のたびに実行されます.
React classのライフサイクル関数に詳しい場合は、useEffect HookをcomponentDidMount、componentDidUpdate、componentWillUnmontの3つの関数の組み合わせと見なすことができます.
これはReact公式サイトの最も基礎的なHooksアプリです
クリアが必要なeffect
なぜeffectで関数を返すのですか?これはeffectオプションのクリアメカニズムです.各effectはクリア関数を返すことができます.これにより、サブスクリプションの追加と削除の論理を一緒に配置できます.これらはeffectの一部に属しています.
Reactはいつeffectをクリアしますか?Reactは、コンポーネントのアンインストール時にパージを実行します.前に学んだように、effectはレンダリングのたびに実行されます.これは、Reactが現在のeffectを実行する前に前のeffectをクリアする理由です.
ここではpropsと仮定します.friend.idは更新100->200->300で更新ロジックを処理するために特定のコードを必要としません.useEffectはデフォルトで処理されるからです.新しいeffectを呼び出す前に、前のeffectをクリーンアップします.これにより、以前のProps変更によるバグが発生しない
不要な副作用関数をスキップする方法
前節の考え方によれば、再レンダリングのたびにこれらの副作用関数を実行するのは明らかに経済的ではありません.どのようにして不要な計算をスキップしますか?useEffectに2番目のパラメータを渡すだけでいいです.2番目のパラメータを使用してreactにこのパラメータの値が変更された場合にのみ、私たちが伝達する副作用関数(最初のパラメータ)が実行されることを伝えます.
拡張:一度だけ実行するeffect(コンポーネントのマウントとアンインストール時のみ実行)を実行する場合は、空の配列([])を2番目のパラメータとして渡すことができます.これはReactにeffectがpropsやstateの値に依存しないことを示しているので、繰り返し実行する必要はありません.これは特別な状況ではありません.配列に依存する動作に従います.
参考文献 https://react-1251415695.cos-...
私たちはDidMountの時にIDで友達のオンライン状態を購読し、メモリの漏洩を防ぐためにWillUnmountで購読をクリアする必要があります.
しかし、コンポーネントが画面に表示されたときにfriend propが変化したときに何が起こるのでしょうか.私たちのコンポーネントは、元の友達の状態を引き続き示します.これはバグです.また、購読をキャンセルする際に誤った友人IDを使用したため、メモリが漏洩したりクラッシュしたりする問題もあります.
class FriendStatus extends React.Component {
constructor(props) {
super(props);
this.state = { isOnline: null };
this.handleStatusChange = this.handleStatusChange.bind(this);
}
componentDidMount() {
ChatAPI.subscribeToFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
}
componentWillUnmount() {
ChatAPI.unsubscribeFromFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
}
handleStatusChange(status) {
this.setState({
isOnline: status.isOnline
});
}
render() {
if (this.state.isOnline === null) {
return 'Loading...';
}
return this.state.isOnline ? 'Online' : 'Offline';
}
}
友達のオンライン購読コンポーネントの最適化
Props更新によるバグを解決するには、DidUpdateで修正購読を行う必要があります.
componentDidMount() {
ChatAPI.subscribeToFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
}
componentDidUpdate(prevProps) {
// friend.id
ChatAPI.unsubscribeFromFriendStatus(
prevProps.friend.id,
this.handleStatusChange
);
// friend.id
ChatAPI.subscribeToFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
}
componentWillUnmount() {
ChatAPI.unsubscribeFromFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
}
Effect Hook
useEffect()は、関数コンポーネントでの副作用操作をデフォルトで実行することができます.これは、最初のレンダリング後と更新のたびに実行されます.
React classのライフサイクル関数に詳しい場合は、useEffect HookをcomponentDidMount、componentDidUpdate、componentWillUnmontの3つの関数の組み合わせと見なすことができます.
これはReact公式サイトの最も基礎的なHooksアプリです
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
});
return (
You clicked {count} times
);
}
クリアが必要なeffect
なぜeffectで関数を返すのですか?これはeffectオプションのクリアメカニズムです.各effectはクリア関数を返すことができます.これにより、サブスクリプションの追加と削除の論理を一緒に配置できます.これらはeffectの一部に属しています.
Reactはいつeffectをクリアしますか?Reactは、コンポーネントのアンインストール時にパージを実行します.前に学んだように、effectはレンダリングのたびに実行されます.これは、Reactが現在のeffectを実行する前に前のeffectをクリアする理由です.
import React, { useState, useEffect } from 'react';
function FriendStatus(props) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
// Specify how to clean up after this effect:
return function cleanup() {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
ここではpropsと仮定します.friend.idは更新100->200->300で更新ロジックを処理するために特定のコードを必要としません.useEffectはデフォルトで処理されるからです.新しいeffectを呼び出す前に、前のeffectをクリーンアップします.これにより、以前のProps変更によるバグが発生しない
// Mount with { friend: { id: 100 } } props
ChatAPI.subscribeToFriendStatus(100, handleStatusChange); // effect
// Update with { friend: { id: 200 } } props
ChatAPI.unsubscribeFromFriendStatus(100, handleStatusChange); // effect
ChatAPI.subscribeToFriendStatus(200, handleStatusChange); // effect
// Update with { friend: { id: 300 } } props
ChatAPI.unsubscribeFromFriendStatus(200, handleStatusChange); // effect
ChatAPI.subscribeToFriendStatus(300, handleStatusChange); // effect
// Unmount
ChatAPI.unsubscribeFromFriendStatus(300, handleStatusChange); // effect
不要な副作用関数をスキップする方法
前節の考え方によれば、再レンダリングのたびにこれらの副作用関数を実行するのは明らかに経済的ではありません.どのようにして不要な計算をスキップしますか?useEffectに2番目のパラメータを渡すだけでいいです.2番目のパラメータを使用してreactにこのパラメータの値が変更された場合にのみ、私たちが伝達する副作用関数(最初のパラメータ)が実行されることを伝えます.
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // count , `document.title`
拡張:一度だけ実行するeffect(コンポーネントのマウントとアンインストール時のみ実行)を実行する場合は、空の配列([])を2番目のパラメータとして渡すことができます.これはReactにeffectがpropsやstateの値に依存しないことを示しているので、繰り返し実行する必要はありません.これは特別な状況ではありません.配列に依存する動作に従います.
参考文献