首页 > 解决方案 > React Hooks 和 React 生命周期方法

问题描述

我是 reactjs 的新手,并且对本机做出反应。当开始学习基础知识时,我发现了关于反应钩子和反应生命周期方法的各种信息。我知道在 react 16.3 之前有 7 个生命周期方法,但现在只有 6 个。任何人都可以详细说明此生命周期方法并通过一些示例对钩子做出反应。这可能有助于我学得更快。谢谢

标签: reactjsreact-nativereact-reduxreact-hooksreact-lifecycle

解决方案


在 React 类中,你有生命周期函数和状态来做事,但你没有在函数组件中拥有它们。React defs 提出了钩子,通过在自定义钩子中捆绑某些功能,您可以简化代码并更好地重用代码。这在以前的类组件中是不可能的。即使使用了 Vue 中使用的 mix-ins,它们现在也拥有与 hooks 类似的组合 api。

假设您想要具有计数器功能,当计数器更改时会记录,具有向上和向下功能和计数器值。

在一个类中,您需要维护您使用 this.up 和 this.down 更改的 this.state.counter,以便您可以在扩展 React.Component 或 React.PureComponent 的 Counter 类中实现它,并拥有一个使用计数器的组件扩展计数器,但该组件仍然可以只有一个计数器。在钩子中,您可以使用自定义钩子实现一个计数器,并在一个组件中拥有多个计数器。

const {
  useState,
  useEffect,
  useCallback,
  useRef,
  memo,
} = React;

//hooks, also custom hooks always start with "use"
const useCounter = (name, initialValue = 1) => {
  //local counter value and function to change it
  const [counter, setCounter] = useState(initialValue);
  //ref created on mount with previous counter value
  const countRef = useRef(initialValue);
  //up and down functions created with useCallback so they
  //  will be created on mount and never change
  const up = useCallback(
    () => setCounter((c) => c + 1),
    []
  );
  const down = useCallback(
    () => setCounter((c) => c - 1),
    []
  );
  //effect that will log when counter changes
  useEffect(() => {
    if (countRef.current !== counter) {
      console.log(`counter ${name} changed to`, counter);
      countRef.current = counter;
    }
  }, [counter, name]);
  //return up, down and counter
  return { up, down, counter };
};
//using memo makes UP2 a pure component so it'll not re
//  render since up is created with useCallback and is
//  not re created therefore the props passed to UP2 
//  don't change
const UP2 = memo(function UP2({ up, name }) {
  console.log(`UP2 for ${name} will only render once`);
  return (
    <button
      onClick={() => {
        //state updates are batched in synchronous
        //  event handlers so "chaged to" will log
        //  only once
        up();
        up();
      }}
    >
      +2
    </button>
  );
});

const App = () => {
  //first counter
  const {
    up: up1,
    down: down1,
    counter: counter1,
  } = useCounter('counter one');
  //second counter
  const {
    up: up2,
    down: down2,
    counter: counter2,
  } = useCounter('counter two', 2);
  return (
    <div>
      <div>
        <button onClick={up1}>UP</button>
        <button onClick={down1}>Down</button>
        <UP2 up={up1} name={'counter one'} />
        {counter1}
      </div>
      <div>
        <button onClick={up2}>UP</button>
        <button onClick={down2}>Down</button>
        <UP2 up={up2} name={'counter two'} />
        {counter2}
      </div>
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>


推荐阅读