UseEffectフックに完全な初心者ガイド


導入


useEffect is a React Hook that is used to handle side effects in React functional components. Introduced in late October 2018, it provides a single API to handle componentDidMount, componentDidUnmount, componentDidUpdate as what was previously done in class-based React components.


どのような効果フックですか?


反応の公式docによると
効果フック、効果、機能部品から副作用を実行する機能を追加
しかし、我々が話しているこれらの副作用は、何ですか?
さて、データ取得、DOMへの変更、ネットワーク要求などのコンポーネントのレンダリング後に何かを行う必要があるということです.これらの種類の操作は効果と呼ばれ、useEffect フック.
エーuseEffect フックはコールバック関数と依存配列の2つのパラメータをとります.
const callbackFunction = () => {  }
dependencyArray = [value1, value2, value3, ...]

useEffect(callbackFunction, dependencyArray)
あるいは、単に上記のものをまとめることができ、通常はコードベースで見ることができます.
useEffect( () => {}, 
  [value1, value2, value3, ...]
)

有効なアクション


カウンタボタンをクリックすると、クリックされたときに1が増加します
function App() {
 const [count, setCount] = React.useState(0)
 return (
  <div>
    <p>{count}</p>
    <button onClick={() => setCount(count + 1)}>click</button>
  </div>
);
}

ReactDOM.render(<App />, document.getElementById("root"));

私はこのカウント値を動的にページのタイトル(すなわちFaviconアイコンの横)に反映させるために、すべてのボタンをクリックする場合はどうですか?
さて、これはコンポーネントによって引き起こされた効果を処理しなければならないので、useEffectフックの完全な使用例を扱います.
一番上にUseEffectをインポートして、コンポーネントの中にフックを呼び出してください.
UseEffectは2つの引数、トリガするコールバック関数と依存配列を受け取ります.
function App() {
  const [count, setCount] = React.useState(0);

  React.useEffect(() => {
    document.title = count;
  });

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));

ここでは、上記の反応コンポーネントがどのように振る舞うかを示します.
  • The App 機能コンポーネントは、HTMLを返し、初期のカウント数を0に設定してUSENTフックに設定します.
  • すぐにuseEffect フックが非同期で実行し、document.title を初期カウントする.
  • 親指の規則は、コンポーネント内の何かが変化したとき(ボタンをクリックしてください)です.the App コンポーネントは、更新された値で再表示されます.
  • をクリックするとincrement からのカウント値を設定するボタン0 to 1 , それはApp コンポーネントを再レンダリングするには、現在の値を更新します.UseEffectは、タイトルを更新されたカウント値に非同期で実行します1
  • 正しいメンタルモデルへの適応


    一方useEffect フックは分離したデモコンポーネントで動作するときに実装するのが簡単に思えます.
    理由は、基礎となる概念の理解とクラスベースの反応ライフサイクル法との連続比較.
    私たちがクラスベースのコンポーネントを使用していた日に戻ってください.コンポーネントの副作用はライフサイクルメソッドを使用して処理されました.componentDidMount , componentDidUpdate and componentWillUnmount APIはライフサイクルメソッドでしたが、それらはどのように扱われるかにおいて異なります.フックにライフサイクルの精神的なモデルを適用すると、不要な&予期しない行動をもたらす可能性があります.
    実際に有用性を把握するためには、ダン・アブラノフが引用したように、物事を行うライフサイクルの方法を「知りません」.
    「*」「使い慣れたクラスライフサイクルメソッドのプリズムを通して、すべてが私のために一緒に来たことを使用してフックを見て停止した後だけです」
    クラス*を最初に作成しましょう.
    class App extends React.Component {
     state = {
      name: ""
     };
    
    componentDidMount() {
      setTimeout(() => {
        console.log("MOUNT", this.state.name);
      }, 3000);
    }
    
    render() {
     return (
      <div>
        <input
        value={this.state.name}
        onChange={(event) => this.setState({ name: event.target.value })}
        />
      </div>
     );
     }
    }
    
    ご覧の通りconsole 3 sの後、メッセージは何をしますか<input /> フィールド?
    componentDidMount 空に印刷するthis.state.name または、入力コンポーネントから最新の値をキャプチャしますか?
    答えは、それが最新の値をキャプチャする理由は、LifeCycleメソッドがクラスベースのコンポーネントで動作する方法です.
    Deleteメソッドを使用してDOMノードを作成します.
    フックがベースの機能部品に同じコードを翻訳するなら、それは全く異なる働きます.機能コンポーネントは、初期状態値を最初のマウントで空にするHTMLノードを返します.useLayoutEffect クラスベースの例をより正確に再現できる別のフックです.ケントCドッドは、これの各々を使うとき、非常によく説明しますpost
    ここでコードで遊んでくださいhere

    依存配列


    2番目のパラメータuseEffect 依存配列です.これは、副作用が/トリガ自体を実行する必要がありますすべての値の配列です.
    たとえば、このカウンターコンポーネントを見てみましょう.ボタンをクリックすると、カウント値が1ずつ増加しますuseState フック.
    function App(){
    
     const [count, setCount] = React.useState(0)
     React.useEffect(() => {console.log("Running Effect")})
     handleChange = () => setCount(prev => prev + 1)
    
    
     return(
      <div> 
        {console.log("COMPONENT RE-RENDER")}
        <h1>Hello</h1>
        <button onClick={handleChange}>click</button>
      </div>
     )
    }
    
    
    ReactDOM.render(<App />, document.getElementById('root'))
    
    
    
    さて、上の例から何を学ぶことができますか?我々が気付くことができるように、あるuseEffect 二番目の引数がないフック.これは、App この場合、変更時に値が返されるたびにcount 値が変化している.したがって、すべてのボタンをクリックすると、コンポーネントは再印刷自体、印刷を続けるCOMPONENT RE-RENDER コンソールに.
    どうやってこれを防ぐのですか
    2番目の引数をuseEffect フック.
    function App(){
    
     const [count, setCount] = React.useState(0)
     React.useEffect(() => {console.log("Running Effect")}, []) 
     handleChange = () => setCount(prev => prev + 1)
    
    
    return(
    <div>   
      {console.log("COMPONENT RE-RENDER")}
      <h1>Hello</h1>
      <button onClick={handleChange}>click</button>
     </div>
      )
    }
    
    
    最初のマウントでは、ログをコンソールに表示します.
    Running Effect
    COMPONENT RE-RENDER
    
    
    しかし、今度は、我々がボタンをクリックするとき、そこからどんなログでもありませんuseEffect 空の配列としてフックするだけで一度だけ実行し、すべての次のログはApp
    Running Effect
    COMPONENT RE-RENDER
    COMPONENT RE-RENDER  // keep logging as many times as the button clicks
    
    
    
    次のステップに進み、依存する配列リストをcount 値は以下の通り:
    React.useEffect(() => {console.log("Running Effect")}, [count])
    
    両方のコンソールテキストを記録するとき、この時間は面白いです.
    Running Effect
    COMPONENT RE-RENDER
    Running Effect
    COMPONENT RE-RENDER
    ... // keep logging both the text for button clicks
    
    
    最初のテキスト(「実行効果」)は、配列の項目が変更されたときに、エフェクトが発生したときに表示されます(このようにカウントされます).
    コンポーネント自体の値が変化しているので、第2のテキスト(「コンポーネント再表示」)は非常に予想されますが、当然ながら、それは最新の値でDOMを更新するために再レンダリングしなければなりません.
    codepen

    不正な依存配列


    依存配列の項目の不適切な使用がデバッグするのが難しい問題につながることに言及する価値があります.反応チームは常に配列の項目を記入し、それらを残していないことをお勧めします.
    非常に役に立つexhaustive-deps このような問題で私たちを助けるstale closure これは間違った依存関係やいくつかの他の理由のためかもしれないと私たちは自動修正を支援します.
    発表についての詳細を読むhere

    クリーンアップ機能の使用法


    我々がこのポストで以前に読んだように.useEffect 未定義の、あるいはオプションのクリーンアップ関数を戻り値として期待します.クリーンアップ機能は、コンポーネントがアンマウントしたときに副作用をクリアする方法と考えることができます.
    useEffect(() => {
      // side effect logic here
    })
    
    // cleanup function
    return () => {
      // logic
    }
    
    クリーンアップ機能を動作させてみましょう.
    function App() {
      const [number, setNumber] = useState(0);
    
      useEffect(() => {
        console.log("number is", number);
        return () => {
          console.log("running cleanup function");
        };
      }, [number]);
    
      return (
        <div className="App">
          <input
            type="number"
            value={number}
            onChange={(e) => setNumber(e.target.value)}
          />
    
          <p>{number}</p>
        </div>
      );
    }
    
    クリーンアップ機能は、タイマーをクリアし、不要なイベントリスナーを掃除するなどの非常に少数のユースケースで使用されています.適切に消毒されていない場合、彼らはMemory leak JavaScriptで.

    バッチの複数の効果


    何が最高の、1つに別の副作用を入れてuseEffect フックまたは複数の?
    正直、それはユースケースに依存し、どのように様々なコンポーネントと相互作用しています.ここで注意する1つの重要な点は、それらが書かれた順序(複数の効用フックがある場合)に、反応が効果を適用するということです
    単一のコンポーネントでこれを行うのは完全に良いです.
    useEffect(() => {
    // Second side effect 
    })
    
    useEffect(() => {
    // First side effect
    })
    
    

    避ける概念的な落とし穴:


    * 1 . UseEffectフックは本当に模倣しませんcomponentDidMount ライフサイクル法.同様にcomponentDidMount & componentDidUpdate . 最終的な結果は実装時に類似しているかもしれませんが、それらが呼び出されマウントされる順序は上記の点で既に議論されているように非常に特徴的です.
    * 2 . UseEffectフックは、クリーンアップ機能を返すことを期待します.undefined . 我々は、他の何かを返さないようにする必要がありますasync 関数は、非同期関数として約束を返します.
    次のコードは、* Effectフックから予期しない約束を返す*
    const App = () => {   
      useEffect(async () => {
        const unsubsribe = await subscriberFunction();    
        return () => {
           unsubscribe()
         }
       }, []) 
    return <div></div>;
    }
    
    今、様々な方法がありますasync 内部関数useEffect フック.私たちはIIFE スタイルテクニック:
    const App = () => {
      useEffect(() => {
    
        async function subscriberFunction() {
          await fetchIds();
        }   
        subscriberFunction();
      }, []);
    return <div></div>;
    };
    
    
    * 3 .*呼び出し中にコンポーネントに問題が指定された順序.

    包装


    反応するuseEffect フックはクラスベースのライフサイクルアプローチから逸脱します.
    把握するには時間と実践が必要だuseEffect's 最高のパターンと基礎概念は、正しく使用すると、信じられないほど強力な反応アプリケーションで副作用を扱うために証明することができます.
    **私が時間をかけて集めた重要なリソース
  • https://overreacted.io/a-complete-guide-to-useeffect/
  • https://stackoverflow.com/questions/53253940/make-react-useeffect-hook-not-run-on-initial-render?rq=1
  • https://reacttraining.com/blog/useEffect-is-not-the-new-componentDidMount/
  • チェンはこのポストが大好きですか?提案を持っているだけでこんにちは言うか?私に手を差し伸べる
    もともと書かれたAbhinav Anshul for Blockchain Works