如何在 React 中使用带有钩子的生命周期方法?

IT技术 javascript reactjs react-native react-hooks
2021-04-14 00:09:01

我已经经历了 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>
   );
  }

如果使用钩子,如何在上述功能组件中使用生命周期方法?

4个回答

以下是最常见生命周期的示例:

componentDidMount

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

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不会在第一次渲染后运行,但此 hooks 版本在每次渲染后运行。

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 文档

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 文档

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

还没有钩子的等价物。

useLayoutEffectgetSnapshotBeforeUpdate. 使用useRef您只能使其在更新时触发,而不能在安装时触发。
2021-05-27 00:09:01
示例中useEffect回调componentWillUnmount 将在每次重新渲染之前调用,而不仅仅是在卸载组件时调用。正确的实现将使用useRef一个[]deps 数组,例如:const onUnmountRef = useRef(() => console.log("componentWillUnmount!")); useEffect(() => onUnmountRef.current, []);
2021-05-29 00:09:01
这是一个干净而完美的答案。谢谢:)
2021-05-30 00:09:01
什么是 componentWillMount?
2021-06-09 00:09:01
接得好。更新
2021-06-14 00:09:01

好吧,你真的没有生命周期方法。=) 但是你可以使用这里显示的效果钩子https://reactjs.org/docs/hooks-effect.html

效果挂钩将能够复制 componentDidMount、componentDidUpdate 和 componentWillUnmount 的行为

所以你真的不需要组件中的生命周期方法。效果钩取而代之。=)

阅读上面的链接,您将获得一些有关它们如何工作的示例。

行。但是如果我想在钩子中使用静态 getDerivedStateFromProps 和 shouldComponentUpdate 方法怎么办?
2021-06-19 00:09:01

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>
   );
 }

在这个例子中,这似乎不是一个巨大的胜利,因为它不是。但是生命周期方法的问题在于您只能在组件中获得其中的一个。如果你想上传到服务器,并触发一个事件,并将一条消息放入队列,而这些都没有关系怎么办?太糟糕了,他们都挤在了一起componentDidUpdate或者,您n为您n想做事情准备了多层包装的 HOC 但是使用钩子,您可以将所有这些拆分为解耦调用,useEffect而无需不必要的 HOC 层。

useEffect 可以多次使用吗?还有钩子中的静态 getDerivedStateFromProps 和 shouldComponentUpdate 怎么样?
2021-06-15 00:09:01
@Think-Twice 是的,您可以根据需要useEffect在组件定义中使用尽可能多的调用因为shouldComponentUpdate该函数有一个可选的第二个参数,它是要监视的值的列表,例如useEffect(uploadToTheServer, [count]). 我不知道,getDerivedStateFromProps因为它渲染之前运行可能仍然需要为该 IDK 使用一个类,这对我来说也是全新的。
2021-06-15 00:09:01

功能组件是纯粹的无状态组件。但是在 React 16.8 中,他们添加了 Hooks。钩子可以用来代替状态和生命周期方法。

是的,您可以将useEffect Hook 视为 Like

  • 组件DidMount

  • componentDidUpdate ,

  • 组件将卸载

  • shouldComponentUpdate结合。

  • 注意它是componentDidMountcomponentDidUpdatecomponentWillUnmount 和 shouldComponentUpdate的紧密替代品