React Hooks和Component Lifecycle等效

Yan*_*Tay 20 javascript reactjs react-hooks

什么的等价物 componentDidMount,componentDidUpdate以及componentWillUnmount使用钩做出反应就像生命周期挂钩useEffect

Yan*_*Tay 41

componentDidMount

传递一个空数组作为第二个参数,useEffect()仅在mount上运行回调.

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")
);
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

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")
);
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

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")
);
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案,对于任何可能不理解[]为什么为componentDidMount起作用的人,这告诉React您的效果不依赖于props或state的任何值,因此它不需要重新运行。/sf/answers/3727738801/ (3认同)

lok*_*ngh 14

为了简单的解释,我想展示一个视觉参考

在此输入图像描述

正如我们在上图中简单看到的那样 -

组件DidMount:

useEffect(() => {        
   console.log('componentWillMount');
}, []);
Run Code Online (Sandbox Code Playgroud)

组件更新:

useEffect(() => {        
   console.log('componentWillUpdate- runs on every update');
});

useEffect(() => {        
   console.log('componentWillUpdate - runs if dependency value changes ');
},[Dependencies]);
Run Code Online (Sandbox Code Playgroud)

组件将卸载:

  useEffect(() => {
    return () => {
        console.log('componentWillUnmount');
    };
   }, []);
Run Code Online (Sandbox Code Playgroud)


Eda*_*rit 7

React docs

如果您熟悉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 */
    }
)
Run Code Online (Sandbox Code Playgroud)

Dan Abramov博客措辞的帮助下,以及我自己的一些补充:

尽管您可以使用这些挂钩,但它并不完全等效。与componentDidMount和不同componentDidUpdate,它将捕获道具和状态。因此,即使在回调内部,您也将看到特定渲染的属性和状态(这意味着在componentDidMount初始的属性和状态中)。如果您想看到“最新”的东西,可以将其写入参考。但是通常有一种更简单的方法来构造代码,以使您不必这样做。返回的函数,它可以替代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>
  );
}
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

如果我们使用类实现:

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

在此处输入图片说明

this.state.count总是指向最新计数,而不是指向特定渲染的计数。