React Hooks 和组件生命周期等价物

新手上路,请多包涵

What are the equivalents of the componentDidMount , componentDidUpdate , and componentWillUnmount lifecycle hooks using React hooks like useEffect ?

原文由 Yangshun Tay 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 335
2 个回答

componentDidMount

将空数组作为第二个参数传递给 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 的回调参数中返回一个回调,它将在卸载之前被调用。

 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>

原文由 Yangshun Tay 发布,翻译遵循 CC BY-SA 4.0 许可协议

来自 React 文档

如果您熟悉 React 类生命周期方法,您可以将 useEffect Hook 视为 componentDidMount、componentDidUpdate 和 componentWillUnmount 的组合。

他们的意思是:

componentDidMount 有点像 useEffect(callback, [])

componentDidUpdate 有点像 useEffect(callback, [dep1, dep2, ...]) - deps 数组告诉 React: “如果其中一个 deps 发生变化,则在渲染后运行回调”

componentDidMount + componentDidUpdate 有点像 useEffect(callback)

componentWillUnmount 是回调的返回函数:

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

借助 Dan Abramov 在他 博客 中的措辞,以及我自己的一些补充:

虽然您可以使用这些挂钩,但它们并不完全等同。与 componentDidMountcomponentDidUpdate 不同,它将 捕获 道具和状态。因此,即使在回调内部,您也会看到特定渲染的道具和状态(这意味着在 componentDidMount 初始道具和状态)。如果你想看到“最新”的东西,你可以把它写给 ref。但是通常有一种更简单的方法来构建代码,因此您不必这样做。应该替代 componentWillUnmount 的返回函数也不是完全等效的,因为该函数将在每次组件重新渲染和组件卸载时运行。请记住,效果的心智模型与组件生命周期不同,试图找到它们的确切等价物可能会让您感到困惑而不是帮助。为了提高工作效率,您需要“考虑效果”,他们的心智模型更接近于实现同步,而不是响应生命周期事件。

来自 Dan 博客的示例:

 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 始终指向 最新 计数,而不是属于特定渲染的计数。

原文由 Edan Chetrit 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题