在React Hooks中使用生命周期方法

React新版本的生命周期

react 16.3之后新增了两个生命周期getDerivedStateFromPropsgetSnapshotBeforeUpdate,并且原来的componentWillMountcomponentWillReceiveProps以及componentWillUpdate将被移除。

constructor

函数组件不用写constructor,用useState初始化state

getDerivedStateFromProps

这个方法基本用来替代componentWillReceiveProps,它是个静态方法,也就是说不能访问this,也就是说不能改this.state

官方栗子

function ScrollView({row}) {
  let [isScrollingDown, setIsScrollingDown] = useState(false);
  let [prevRow, setPrevRow] = useState(null);

  if (row !== prevRow) {
    // 上次渲染后row发生变化  更新isScrollingDown.
    setIsScrollingDown(prevRow !== null && row > prevRow);
    setPrevRow(row);
  }

  return `Scrolling down: ${isScrollingDown}`;
}

shouldComponentUpdate

使用React.memo,类似PureComponent,但它只对比props的变化

const Demo = React.memo((props) => {
  // ...
})

对子组件可以使用useMemo

function Parent({ a, b }) {
  // 只在a变化时re-render
  const child1 = useMemo(() => <Child1 a={a} />, [a]);
  // 只在b变化时re-render
  const child2 = useMemo(() => <Child2 b={b} />, [b]);
  return (
    <>
      {child1}
      {child2}
    </>
  )
}

render

那就是函数它自个儿了……

下面几个可以使用useEffect(fn, [...watchStates])实现的

componentDidMount

第二个参数传空数组

这么写在useEffect里使用一些state的时候会报错"missing dependency",暂时用了eslint-disable-line

function Demo () {
  const [title, setTitle] = useState('hello');

  useEffect(() => {
    document.title = title;
    // do ...
  }, []); // eslint-disable-line

   // 点击文字是 hello world world .... 但是页面title是hello
  return (
    <div onClick={() => setTitle(title + ' world')}>{title}</div>
  );
}

componentDidUpdate

只传一个参数,每次render就都会调用这个函数,和componentDidUpdate不同的是第一次render也会执行它

function Demo () {
  const [title, setTitle] = useState('hello');

  useEffect(() => {
    document.title = title;
    // do ...
  });

  return (
    <div onClick={() => setTitle(title + ' world')}>{title}</div>
  );
}

如果不希望在第一次(初始)render时候调用,可以:

function Demo () {
  const [title, setTitle] = useState('hello');
  const first = useRef(true);

  useLayoutEffect(() => {
    if (first.current) {
      first.current = false;
      return;
    }

    document.title = title;
    console.log("componentDidUpdateFunction");
  });

  return (
    <div onClick={() => setTitle(title + ' world')}>{title}</div>
  );
}

componentWillUnmount

在useEffect的第一个函数参数中返回一个函数,这个函数就会在unmount时候被调用

function Demo () {
  const [title, setTitle] = useState('hello');

  useEffect(() => {
    return () => {
      console.log('componentWillUnmount')
    }
  });

  return (
    <div onClick={() => setTitle(title + ' world')}>{title}</div>
  );
}

最后最后componentDidCatchgetDerivedStateFromError暂时还不能用Hook来实现,暂时。

参考:
javascript - How to use lifecycle methods with hooks in React? - Stack Overflow

javascript - Make React useEffect hook not run on initial render - Stack Overflow

Hooks FAQ – React

GitHub - wojtekmaj/react-lifecycle-methods-diagram: Interactive React Lifecycle Methods diagram.

Comments
Write a Comment