web-dev-qa-db-ja.com

Reactでライフサイクルメソッドをフックで使用する方法は?

反応v16.7.0で導入されたフックを使用しました。

https://reactjs.org/docs/hooks-intro.html

したがって、フックについての私の理解は、reactでクラスコンポーネントを記述することなく、機能コンポーネントの状態を操作できることです。これは本当に素晴らしい機能です。

しかし、機能コンポーネントでフックを使用することについて、明確なイメージが得られていません。

   import { useState } from 'react';

   function Example() {
   const [count, setCount] = useState(0);

    return (
      <div>
        <p>You clicked {count} times</p>
        <button onClick={() => setCount(count + 1)}>
         Click me
        </button>
      </div>
   );
  }

フックを使用する場合、上記の機能コンポーネントでライフサイクルメソッドを使用するにはどうすればよいですか?

10
Hemadri Dasari

最も一般的なライフサイクルの例を次に示します。

componentDidMount

空の配列を2番目の引数としてuseEffect()に渡し、マウント時にのみコールバックのみを実行します。

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  }, []); // Pass an empty array to run only callback on mount only.

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

componentDidUpdate(緩い)

単一の引数をuseEffectに渡すだけで、レンダリングのたびに実行されます。 componentDidUpdateは最初のレンダリング後に実行されないが、このフックバージョンはすべてのレンダリング後に実行されるというわずかな違いがあるため、これは緩やかな同等です。

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  }); // No second argument, so run after every render.

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

componentDidUpdate(厳密)

この例と上記の例の違いは、ここのコールバックは最初のレンダリングでは実行されず、componentDidUpdateのセマンティクスを厳密にエミュレートすることです。これ 答えはTholleによる 、すべてのクレジットは彼に送られます。

function Example() {
  const [count, setCount] = useState(0);

  const firstUpdate = useRef(true);
  useLayoutEffect(() => {
    if (firstUpdate.current) {
      firstUpdate.current = false;
      return;
    }

    console.log('componentDidUpdate');
  });

  return (
    <div>
      <p>componentDidUpdate: {count} times</p>
      <button
        onClick={() => {
          setCount(count + 1);
        }}
      >
        Click Me
      </button>
    </div>
  );
}

componentWillUnmount

useEffectのコールバック引数でコールバックを返すと、アンマウントする前に呼び出されます。

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    // Return a callback in useEffect and it will be called before unmounting.
    return () => {
      console.log('componentWillUnmount!');
    };
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

shouldComponentUpdate

React.PureComponentまたはReact.memoを使用して、コンポーネントレベルで既にこれを実現できます。子コンポーネントの再レンダリングを防ぐために、この例は React docs から取得されます。

function Parent({ a, b }) {
  // Only re-rendered if `a` changes:
  const child1 = useMemo(() => <Child1 a={a} />, [a]);
  // Only re-rendered if `b` changes:
  const child2 = useMemo(() => <Child2 b={b} />, [b]);
  return (
    <>
      {child1}
      {child2}
    </>
  )
}

getDerivedStateFromProps

繰り返しますが、 React docs

function ScrollView({row}) {
  let [isScrollingDown, setIsScrollingDown] = useState(false);
  let [prevRow, setPrevRow] = useState(null);

  if (row !== prevRow) {
    // Row changed since last render. Update isScrollingDown.
    setIsScrollingDown(prevRow !== null && row > prevRow);
    setPrevRow(row);
  }

  return `Scrolling down: ${isScrollingDown}`;
}

getSnapshotBeforeUpdate

フックに相当するものはまだありません。

componentDidCatch

フックに相当するものはまだありません。

22
Yangshun Tay

Reactチームはこの目的のためにuseEffectフックを提供しました。例のコンポーネントを取り、カウントのためにサーバーのアップロードを追加しましょう。そうでなければ、たとえばcomponentDidUpdateに入れます:

 import { useState, useEffect } from 'react';

 function Example() {
   const [count, setCount] = useState(0);
   useEffect(() => {
     fetch(
       'server/url',
       {
         headers: {
           'Accept': 'application/json',
           'Content-Type': 'application/json'
         },
         body: JSON.stringify({count}),
       }
     ); 
   });

   return (
     <div>
       <p>You clicked {count} times</p>
       <button onClick={() => setCount(count + 1)}>
         Click me
       </button>
     </div>
   );
 }

それはそうではないので、これはこの例では大きな勝利のようには見えません。しかし、ライフサイクルメソッドの問題は、コンポーネントでそれぞれ1つしか取得できないことです。サーバーにアップロードし、イベントをトリガーし、メッセージをキューに入れて、それらがどれも関連していない場合はどうでしょうか?残念なことに、それらはすべてcomponentDidUpdateに詰め込まれています。または、やりたいn事柄のために、nラップされたHOCのレイヤーがあります。ただし、フックを使用すると、不要なHOCレイヤーなしで、これらすべてをuseEffectへの分離された呼び出しに分割できます。

2
Jared Smith

まあ、あなたは本当にライフサイクルメソッドを持っていません。 =)しかし、ここに示すようにエフェクトフックを使用できます https://reactjs.org/docs/hooks-effect.html

エフェクトフックは、componentDidMount、componentDidUpdate、およびcomponentWillUnmountの動作を複製できます。

したがって、コンポーネントにライフサイクルメソッドは本当に必要ありません。代わりに、エフェクトフックが代わりに使用されます。 =)

上記のリンクを読むと、それらがどのように機能するかについていくつかの例が得られます。

2
weibenfalk