React hooks完成生命周期函数

React 的生命周期函数在类组件的年代起着至关重要的效果,它们帮助开发者掌控组件的创立、更新和毁掉过程。但是,在 React 16.8 版别中,引入了 Hooks API,然后敞开了函数式组件的新纪元。Hooks 供给了一系列的内置函数(如 useState, useEffect, useContext, useReducer 等),使得在函数式组件中能够运用 React 特性,包含状况办理、副效果处理等。本文测验探究怎么运用这些 Hooks 在函数式组件中完成与类组件生命周期函数相似的功用。

类组件的生命周期函数

在深化 Hooks 之前,先回忆一下类组件中的首要生命周期函数:

  • constructor:组件实例化时调用,用于初始化状况和绑定办法。
  • componentDidMount:组件挂载完成后调用,合适履行依靠 DOM 的操作、发送网络恳求等。
  • shouldComponentUpdate:在接收到新的 props 或 state 之后,烘托前调用,依据回来的布尔值决定是否更新组件。
  • componentDidUpdate:组件更新后调用,能够处理组件更新的逻辑。
  • componentWillUnmount:组件毁掉前调用,合适履行清理使命,如取消订阅、铲除定时器等。
  • getSnapshotBeforeUpdatecomponentDidCatch 分别用于在更新前获取 DOM 信息和捕获后代组件过错。

Hooks 完成生命周期函数功用

Functions 尽管不像类组件那样具有明确命名的生命周期办法,但能够运用 React Hooks 来完成相似的功用。

1. 完成 componentDidMount 和 componentWillUnmount

useEffect 是完成 componentDidMountcomponentWillUnmount 功用的关键

import React, { useEffect } from 'react';
function SampleComponent() {
  useEffect(() => {
    // componentDidMount 的代码
    console.log('Component did mount.');
    // componentWillUnmount 的代码
    return () => {
      console.log('Component will unmount.');
    };
  }, []);
  return <div>Hello, world!</div>;
}

上述代码中,useEffect回调函数会在组件挂载完毕后调用,相似于 componentDidMount。回来的函数会在组件卸载时调用,相似于 componentWillUnmount。依靠项数组 [] 保证了这个效果只运转一次。

2. 完成 shouldComponentUpdate

运用 useEffect 合作 useStateuseMemo 能够完成 shouldComponentUpdate 的功用。

import React, { useState, useEffect } from 'react';
function SampleComponent(props) {
  const [shouldUpdate, setShouldUpdate] = useState(false);
  useEffect(() => {
    if (props.someValue !== someOldValue) {
      // 相似于 shouldComponentUpdate 的逻辑
      setShouldUpdate(true);
    }
  }, [props.someValue]);
  return <div>{shouldUpdate ? 'Component should update.' : 'Component should not update.'}</div>;
}

在此示例中,依靠数组包含了 props.someValue,只有 someValue 改变时,副效果才会运转,相似于类组件中通过 shouldComponentUpdate 控制的重烘托逻辑。

3. 完成 componentDidUpdate

useEffect 能够运用依靠项数组来模仿 componentDidUpdate 的功用。

import React, { useState, useEffect } from 'react';
function SampleComponent({ someValue }) {
  const [stateValue, setStateValue] = useState(someValue);
  useEffect(() => {
    // componentDidUpdate 的逻辑
    console.log('Component did update.');
  }, [someValue]);  // 只有 someValue 变化时,才会履行
  return <div>Updated state value: {stateValue}</div>;
}

在这个例子中,代码块内的逻辑会在 someValue 更新时履行,就相当于 componentDidUpdate 办法的行为。

4. 实拟 getSnapshotBeforeUpdate

useEffect 并不直接支撑 getSnapshotBeforeUpdate 的行为模仿。在大多数情况下,能够通过 DOM 操作来到达相似成果。

import React, { useRef, useLayoutEffect } from 'react';
function SampleComponent() {
  const elementRef = useRef();
  useLayoutEffect(() => {
    const snapshot = elementRef.current.scrollHeight;
    return () => {
      // 在 DOM 更新后,该代码块履行
      if (elementRef.current.scrollHeight !== snapshot) {
        // 对应 getSnapshotBeforeUpdate 的逻辑
        console.log('Layout changed.');
      }
    };
  });
  return <div ref={elementRef}>Some content</div>;
}

运用 useLayoutEffect 在 DOM 更新阶段同步履行代码块,能够获取和前一个 DOM 状况相关的信息。

5. 实拟 componentDidCatch

useEffect 不供给捕获反常的能力。React 现在并没有供给在函数式组件中直接捕获子组件反常的 Hooks。仍需运用类组件中的 componentDidCatch 或 React 16+ 供给的 static getDerivedStateFromError

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }
  static getDerivedStateFromError(error) {
    return { hasError: true };
  }
  componentDidCatch(error, info) {
    logErrorToMyService(error, info);
  }
  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children;
  }
}

将函数式组件包裹在 ErrorBoundary 类组件中,能够对其子组件的过错进行捕获并处理。

结论

尽管函数式组件没有类组件中明确定义的生命周期办法,但是通过运用 Hooks API,能够完成几乎所有相关的功用。这种新的模式供给了愈加灵活和可复用的方式来处理组件的生命周期事情,同时简化了组件的逻辑和结构。随着 Hooks 的老练和社区的广泛采用,函数式组件已成为 React 使用开发的未来趋势。

在过渡到全函数式编程的过程中,有时仍需要将类组件与函数式组件混合运用,尤其是在处理已有项目或杂乱的生命周期逻辑时。了解并掌握怎么在函数式组件中模仿类组件的生命周期函数,对于 React 开发者来说,无疑是一项名贵的技能。