ずっと昔、私たちはクラスで React を使用していました。覚えていますか?
当時、私たちはライフサイクル メソッド、つまり特定の瞬間に実行されるコールバックを受け入れるクラスのメソッドという概念を持っていました。大きな 3 つ: マウント時、更新時、アンマウント時。
これは重要でした。クラス コンポーネントでは、返される JSX は render メソッドで作成され、状態はコンポーネントの this に付加され、アプリ開発者は特定の瞬間にアクションを実行する方法を知る方法が必要でした。私たちはコンポーネントの寿命について次のような考えを持っていました:
そしてもちろん、React 状態の更新に接続しない外部データを使用している場合に、再レンダリングを手動でトリガーできる、forceUpdate などの重要な API がありました。
概念的なレベルでは、アプリのフローを実行するより直接的な方法があります。ライフサイクル メソッドは DOM 要素の同様のライフ サイクルに従い、自分でメモや ForceUpdate を実行でき、状態の同期がロジックを実行するデフォルトの方法でした。
この直接性は単純さとみなされ、これらの概念を学ぶのはリアクティブ モデルに比べて簡単でした。しかしその後、フックが登場し、すべてが変わりました。
移行は混乱を招きました。まず、開発者が抱いていた React モデルの概念的なビジョンを簡単に維持するために、多くのコミュニケーションがフック モデルの類似点を示そうとしました。 3 つの主要なライフ サイクル メソッドを実現するために、useEffect を使用した回避策が示されました。
// componentDidMount useEffect(() => { // code... // componentWillUnmount: return function cleanup() { // code... }; }, []); // componentDidUpdate useEffect(() => { // code... }, [dependencyState, dependencyProp]);
したがって、フックを使用して作成された新しい React コードのほとんどはこの考え方に従っており、状態の同期を開始するのは自然なプロセスでした。ライフサイクル メソッドの同じ考え方を維持するために、setState を呼び出して再レンダリング プロセスをトリガーする場所になりました。
何が問題ですか?
状態の同期が問題になり、useEffect の間違った使用法が問題になり、2 回の再レンダリングが問題になり、再レンダリングの多さが問題になり、パフォーマンスが問題になりました。
React からのこのステップは、少なくとも私にとっては少しわかりにくいです。なぜなら、フックへの移行は、たとえ粗いモデルであっても、リアクティブ モデルへの移行を意味するからです。しかし、実際に大きな変化は何もなかったということでした。反応性の概念や理論に関する内容はなく、React を何年も使って働いていても、反応性とソリッドに関する Ryan Carniato のブログ投稿を読んで、反応性を本当に理解し始めたところです。
useEffect に誤用があることは知っていても、その理由がまったく理解できませんでした。反応性に関する概念理論が欠如しているため、フックで間違いを犯しやすくなります。 useEffect は最も嫌われているフックとなり、一部の人々からは 「useFootgun」 と呼ばれています。重要なのは、React には概念的な混乱があり、それが今日私たちが目にする useEffect に関するすべての問題として表れているということです。
useEffect の問題は問題の原因ではなく、結果です。
それで、これが問題です。反応性の概念にはライフサイクルはありません。
あなたには変化があり、それに反応して副作用が生じます。結果は結果であり、原因ではありません。状態の同期やマウントとアンマウントの概念はありません。
それがアンマウント前の最初のレンダリングであるか、10 番目のレンダリングであるか、または最後のレンダリングであるかは問題ではありません。また、フックでは、useEffect でさえもそれを考慮しません。
試してみましょう:
// componentDidMount useEffect(() => { // code... // componentWillUnmount: return function cleanup() { // code... }; }, []); // componentDidUpdate useEffect(() => { // code... }, [dependencyState, dependencyProp]);
状態が更新されるたびに両方の関数が実行されていることがコンソールに表示されます。最初にクリーンアップコール、次にエフェクトコールバックです。 useEffect を何らかの状態またはプロパティで使用してサブスクリプションを実行している場合、依存関係が変更されるたびに、クリーンアップ関数が呼び出され、次に新しいコールバックが呼び出され、新しい値を使用してサブスクリプションを再度実行します。
アプリのコードは React モデルを簡略化したものとして見る必要があります。
function EffectExample() { const [count, setCount] = useState(0); useEffect(() => { console.log('effect', count); return () => { console.log('clean up', count); } }, [count]); return ( <button onClick={() => setCount((state) => state + 1)}> {count} </button> ) }
次のようなコンポーネントがある場合:
UI = fn(state)
ボタンをクリックしてカウントに 1 を追加すると、概念的には、実際には次のようなものになります。
function Example() { const [count, setCount] = useState(0); return ( <button onClick={() => setCount((state) => state + 1)}> {count} </button> ) }
クリックするたびに、新しい状態で fn が再度呼び出され、新しいバージョンの UI が生成されます。状態は、ユーザーのアクション、または非同期導出で作成される非同期値によって変化する必要があります。
こうすることでクリーンなアイデアを維持できます:
画面への要素の追加、更新、削除を行うのはレンダラーの問題です。コンポーネントレベルで重要なのは次のとおりです:
フックとそのリアクティブ モデルにより、React 自体がブラウザーから切り離され、アプリのコードは画面レンダリング プロセスのどの時点にあるかを気にしなくなります。もう更新を強制する必要はなく、独自のルールでメモを処理することさえできます。アプリ開発者にとっては直接的ではありませんが、モデルに関してはより直接的です。
再レンダリングするたびに構造が生成され、残りは React が処理します。
以上がフックを使用した React にはライフサイクルが存在しませんの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。