38

のような React フックを使用する、、、およびライフサイクル フックcomponentDidMountcomponentDidUpdate相当するものは何 ですか?componentWillUnmountuseEffect

4

4 に答える 4

59

componentDidMount

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

function ComponentDidMount() {
  const [count, setCount] = React.useState(0);
  React.useEffect(() => {
    console.log('componentDidMount');
  }, []);

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

ReactDOM.render(
  <div>
    <ComponentDidMount />
  </div>,
  document.querySelector("#app")
);
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>

componentDidUpdate

componentDidUpdate()更新が発生した直後に呼び出されます。このメソッドは、最初のレンダリングでは呼び出されません。useEffect最初を含むすべてのレンダリングで実行されます。したがって、 と厳密に同等にしたい場合componentDidUpdateは、 を使用useRefして、コンポーネントが一度マウントされているかどうかを判断する必要があります。さらに厳密にしたい場合は、 を使用しますuseLayoutEffect()が、同期的に起動します。ほとんどの場合、これuseEffect()で十分です。

この回答は Tholle に触発されたものであり、すべての功績は彼にあります。

function ComponentDidUpdate() {
  const [count, setCount] = React.useState(0);

  const isFirstUpdate = React.useRef(true);
  React.useEffect(() => {
    if (isFirstUpdate.current) {
      isFirstUpdate.current = false;
      return;
    }

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

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

ReactDOM.render(
  <ComponentDidUpdate />,
  document.getElementById("app")
);
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>

componentWillUnmount

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

function ComponentWillUnmount() {
  function ComponentWillUnmountInner(props) {
    React.useEffect(() => {
      return () => {
        console.log('componentWillUnmount');
      };
    }, []);

    return (
      <div>
        <p>componentWillUnmount</p>
      </div>
    );
  }
  
  const [count, setCount] = React.useState(0);

  return (
    <div>
      {count % 2 === 0 ? (
        <ComponentWillUnmountInner count={count} />
      ) : (
        <p>No component</p>
      )}
      <button
        onClick={() => {
          setCount(count + 1);
        }}
      >
        Click Me
      </button>
    </div>
  );
}

ReactDOM.render(
  <div>
    <ComponentWillUnmount />
  </div>,
  document.querySelector("#app")
);
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>

于 2018-11-11T22:49:26.000 に答える
15

React ドキュメントから:

React クラスのライフサイクル メソッドに精通している場合は、useEffect フックを componentDidMount、componentDidUpdate、および componentWillUnmount を組み合わせたものと考えることができます。

そのことわざによって、彼らは次のことを意味します。

componentDidMountは一種のuseEffect(callback, [])

componentDidUpdateは一種のものですuseEffect(callback, [dep1, dep2, ...])- deps の配列は Reactに「deps の 1 つが変更された場合、レンダリング後にコールバックを実行します」と伝えます。

componentDidMount + componentDidUpdateは一種のuseEffect(callback)

componentWillUnmountは、コールバックから返された関数の一種です。

useEffect(() => { 
    /* some code */
    return () => { 
      /* some code to run when rerender or unmount */
    }
)

Dan Abramovのブログからの言い回しと、私自身のいくつかの追加の助けを借りて:

これらのフックを使用できますが、完全に同等ではありません。と とは異なりcomponentDidMount、小道具と状態componentDidUpdateキャプチャします。したがって、コールバック内でも、特定のレンダリングの小道具と状態が表示されます (つまりcomponentDidMount、最初の小道具と状態で)。「最新」のものを見たい場合は、それを ref に書き込むことができます。しかし、通常、コードを構造化するより簡単な方法があり、その必要はありません。に代わると思われる返された関数componentWillUnmountコンポーネントが再レンダリングされるたびに、およびコンポーネントがアンマウントされるときに関数が実行されるため、これも完全に同等ではありません。効果のメンタル モデルはコンポーネントのライフサイクルとは異なることに注意してください。正確に同等のものを見つけようとすると、助けになるどころか混乱する可能性があります。生産性を高めるには、「効果を考える」必要があり、彼らのメンタル モデルは、ライフサイクル イベントへの対応よりも同期の実装に近いものです。

ダンのブログからの例:

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

  useEffect(() => {
    setTimeout(() => {
      console.log(`You clicked ${count} times`);
    }, 3000);
  });

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

ここに画像の説明を入力

クラスの実装を使用する場合:

componentDidUpdate() {
  setTimeout(() => {
    console.log(`You clicked ${this.state.count} times`);
  }, 3000);
}

ここに画像の説明を入力

this.state.count特定のレンダリングに属するものではなく、常に最新のカウントを指します。

于 2019-04-03T19:03:51.247 に答える
3

以下はReact Hooks FAQからの良い要約で、クラスのライフサイクル メソッドに相当するフックをリストしています。

constructor: 関数コンポーネントにはコンストラクターは必要ありません。呼び出しで状態を初期化できますuseState。初期状態の計算にコストがかかる場合は、関数を に渡すことができますuseState

getDerivedStateFromProps:代わりに、レンダリング中に更新をスケジュールします。

shouldComponentUpdate:以下のReact.memo を参照してください。

render: 機能部品本体です。

componentDidMount, componentDidUpdate, componentWillUnmount:useEffectフックは、これらのすべての組み合わせを表現できます (あまり 一般的でないケースを含む)。

componentDidCatchand getDerivedStateFromError:これらのメソッドに相当するフックはまだありませんが、すぐに追加される予定です。


componentDidMount

useEffect(() => { /*effect code*/ }, []);

[]マウント時に一度だけ効果を実行します。通常、依存関係を指定する方が適切です。と同じレイアウト タイミングにするcomponentDidMount場合は、 を参照してくださいuseLayoutEffect(ほとんどの場合は必要ありません)。

componentWillUnmount

useEffect(() => { /*effect code*/ ; return ()=> { /*cleanup code*/ } }, [deps]); 

componentWillUnmountcleanupの効果に対応します。

componentDidUpdate

const mounted = useRef();
useEffect(() => {
  if (!mounted.current) mounted.current = true;
  else {
    // ... on componentDidUpdate 
  }
});

と同じレイアウト タイミングにするcomponentDidUpdate場合は、 を参照してくださいuseLayoutEffect(ほとんどの場合は必要ありません)。同等のフックの詳細については、この投稿も参照してください。componentDidUpdate

于 2020-03-07T12:35:51.693 に答える