エフェクトフック


私は最近、反応の作り付けについて学んだuseEffect フックと私を教えてみましょう-それはきちんとした!💙 これは一般的に外部APIからデータを取得し、タイマーを処理するために使用されます.この記事は、タイマーコンポーネントのステップバイステップの実装を介してuseEffect フック.
タイマーコンポーネントは次のように各秒を更新してください

あなたが反応するのが新しいならば、あなたは以下の通りあなたの構成要素の最上位レベルで間隔を定義するよう誘われるかもしれません:
import React, { useState } from "react";
import "./TimerDemo.css";

const TimerDemo = () => {
  const [seconds, setSeconds] = useState(0);

 setInterval(() => {
    setSeconds((s) => s + 1);
  }, 1000);

  return (
    <div className="TimerDemo">
      <h1>Timer Demo</h1>
      <div> {seconds} </div>
    </div>
  );
};

export default TimerDemo;
ただし、上記のコードは次の出力になります.

何が起こっているのですか.宇宙を壊して、時空の規則を変えて反応しましたか?👽 いいえ.ここで起こっていることは、複数の間隔が迅速に連続して設定されていることです.
コンポーネントが初めてレンダリングされると、間隔が設定され、seconds 毎秒.状態が変化すると、コンポーネント全体の再レンダリングが直ちに開始され、コンポーネント内のコードがもう一度実行されます.実行すると、コードが設定され、別の、同じ間隔になります.しかし、古い間隔はまた、そのことをしてseconds .
したがって、現在2つの間隔を持っています.二つの間隔があります.各再レンダリングは、順番に状態変更をトリガする設定されているより新鮮な間隔につながるでしょう.このサイクル-正のフィードバックループ-広告の無限(または可能性が高い広告ブラウザのcrashum)を繰り返します.🔁
反応のタイマーを処理する正しい方法は、見事なuseEffect フック.このフックについて知っているトップ3は以下の通りです.
  • 第1引数としてコールバック関数を受け付ける
  • オプションの2番目の引数として配列を受け取ります
  • NULLを返しますが、必要に応じて関数を返すようにカスタマイズすることができます
  • フック絵文字のクロスブラウザのサポートがまだないので、顔文字を表示するのは難しいです⚓ (大丈夫、これはボーナスだった)
  • これらのポイントの各々がどのように反応するタイマーを扱うかについて調べます.(絵文字を除く)

    コールバック関数


    フックが受け入れる最初の引数はコールバック関数です.この関数は、反応することを理解することです.この場合、効果は我々の間隔です.内部で定義しましょうuseEffect フック.
    const TimerDemo = () => {
      const [seconds, setSeconds] = useState(0);
    
      useEffect(() => {
        setInterval(() => {
          setSeconds((s) => s + 1);
        }, 1000);
      });
    
      return (
        <div className="TimerDemo">
          <h1>Timer Demo</h1>
          <div> {seconds} </div>
        </div>
      );
    };
    
    これは次のように表示されます.

    我々が望むものではなく、我々の問題は残っている.これはuseEffect フックは遊びに入ります.

    エフェクト依存配列


    2番目の引数は、状態やprop値の任意の配列です.ここでは3つのオプションがあります.
  • 配列が削除された場合、前のコードスニペットのように、すべてのレンダリング後にその効果が実行されます.
  • 空の配列:効果は、最初のレンダリングの後に一度実行されます.
  • 状態またはprop値を持つ配列:これらの値のいずれかが変更された場合にのみ実行されます.
  • 我々の場合は、我々は[seconds] , 我々は、反応の効果を再実行するたびにseconds 変更点もちろん、それは完全に無意味であるでしょう-実際、これはまさに我々が避けようとしているものです.
    そして、それを避けることができます具体的には、空の依存配列を渡します.[] . 空の配列は、コンポーネントが初めてレンダリングされた後、一度だけ効果を実行するように反応します.以下のコードを調べましょう.
    const TimerDemo = () => {
      const [seconds, setSeconds] = useState(0);
    
      useEffect(() => {
        setInterval(() => {
          setSeconds((s) => s + 1);
        }, 1000);
      }, []);
    
      return (
        <div className="TimerDemo">
          <h1>Timer Demo</h1>
          <div> {seconds} </div>
        </div>
      );
    };
    

    Voila!タイマーは現在動作します.

    返り値関数


    しかし、DOMからタイマーコンポーネントを削除した場合、何が起こるでしょうか?別のコンポーネント、クロック、それをタイマーコンポーネントをトグルしてラップして削除されるシナリオを作成しましょう.また、DOMにタイマーコンポーネントを削除または追加するトグルボタンを入れましょう.
    const Clock = () => {
      const [isHidden, setIsHidden] = useState(false);
      const toggle = () => setIsHidden((hidden) => !hidden);
    
      return (
        <div className="Clock">
          {!isHidden && <TimerDemo />}
          <button class="Clock-btn" onClick={toggle}>
            Toggle
          </button>
        </div>
      );
    };
    

    まず、DOMからTimeRememorコンポーネントを削除すると、意図通りに動作します.しかし、コンソールを開くと、怒っている赤い海が現れます.反応は幸福ではない.😡

    これはなぜですか.さて、コンポーネントが削除されると、視覚的に消えるにもかかわらず、それに関連付けられている間隔は、単に進み続けます.実行を停止するように言う何もありません.インターバルは、現在の未実装のコンポーネントの状態を試してみて更新します.貧しい反応!🥺
    そこで、どのようにコンポーネントをDOMから削除されたときに停止する間隔を教えますか?指定によってuseEffect '返り値デフォルトではNULLを返しますが、コールバック関数を返すためにこれを変更することができます.警告:クリーンアップ機能は、ビットを抽象的に読むために感じることができる、それを使用して、その機能を最初に手を探索する最良の方法です.
    クリーンアップは次の時間で実行されます.
  • 最初のレンダリングの後、フックは効果を呼び出します.クリーンアップ機能は動作しません
  • すべての次の再レンダリングでは、前の効果実行からのクリーンアップが最初に呼び出され、その後、現在のエフェクトが実行されます
  • クリーンアップもコンポーネントがアンマウントされた後に実行されます
  • クリーンアップ機能を定義しましょう.間隔を停止するには、間隔IDをキャプチャし、Aに渡す必要がありますclearInterval 機能(バニラJS概念).我々は、我々の内部でこの機能を返しますuseEffect そして、実行のシーケンスをモニターするために若干のprint文を加えてください.
      useEffect(() => {
        console.log("I am the effect. PARTY! 🎺 👐 🎉");
        const timerId = setInterval(() => {
          setSeconds((s) => s + 1);
        }, 1000);
    
        return () => {
          console.log("Cleaning up... 🙄 🧹🧼");
          clearInterval(timerId);
        };
      }, []);
    

    この場合、効果はコンポーネントがマウントされたときに実行されますが、2度目の引数である依存関係の配列が空であるため、再び二度とできません.したがって、クリーンアップ機能は、コンポーネントがアンマウントされたときのみ実行され、それにより間隔をクリアし、エラーメッセージを防止します.トグルボタンは、現在意図して動作し、反応するので、かろうじてその興奮を含めることができます幸せです.
    私はあなたも、このチュートリアルを介してそれを作った後、願っています!👏