React组件的生命周期理解

我只是一个虾纸丫 提交于 2020-02-23 15:11:54

React组件的生命周期理解

React组件的生命周期分为初始化,更新,销毁,错误处理四个阶段,每一个阶段又有若干个函数以响应不同的阶段。
生命周期函数图解:
生命周期图解

初始化阶段的钩子函数

在组件初始化阶段会执行

1. constructor

  • React类组件的构造函数在挂载之前被调用。在constructor构造函数中,先调用super(props),将父组件传来的props绑定,在此函数中可以初始化state,将事件处理函数绑定到类实例上。

2. static getDerivedStateFromProps(props,state)

  • getDerivedStateFromProps 是react16.3 之后新增的钩子函数,在组件实例化后,和接受新的props后被调用。他必须返回一个对象来更新状态,或者返回null表示不更新,父组件的props更新,所带来的的重新渲染也会触发此方法。在react16.3之前使用的是constructor+componentWillMount()。

3. render()

  • render()方法在组件中是必须的,在render()函数中以jsx语法创建dom元素,或者渲染this.props和this.state中的数据
  • 返回null。什么也不渲染
  • 布尔值。什么都不渲染
  • render()方法必须是一个纯函数,不应该改变state,也不能直接和浏览器进行交互,应该将事件放在其他钩子函数中

4. componentDidMount

  • 此函数在render()执行之后执行,表示组件挂载完成,所以一般在这里进行ajax请求数据
	componentDidMount(){
		//此钩子函数在render()函数之后执行,通常进行ajax获取数据
		axios.get("http://xxx.com").then((res) => {
			this.setState(){
				list.res.list
			}
		})
	}

更新阶段的钩子函数

组件更新阶段执行

1. static getDreivedStateFromProps(props,state)

  • 此方法与挂载阶段的方法一样在render()方法自谦调用,并且在初始挂载及后续更新时都会被调用。返回一个对象来更新state

2. shouldComponentUpdate()

  • 此函数根据返回值,判断React组件的输出是否受当前state或props更改的影响。默认行为是state每次发生变化都会重新渲染。
  • 该函数仅作为性能优化的方式而存在。即当使用该函数时,props,或者state数据没有发生变化时不会执行之后的钩子函数。不要企图依靠此方法来“阻止”渲染,因为这可能会产生 bug。你应该考虑使用内置的 PureComponent 组件,而不是手动编写 shouldComponentUpdate()。PureComponent 会对 props 和 state 进行浅层比较,并减少了跳过必要更新的可能性。

3. render()

4. getSnapshotBeforeUpdate(prevProps,prevState)

  • getSnapshotBeforeUpdate()在最近一次渲染输出之前调用。他可以捕获渲染之前的状态,并且此钩子函数的返回值会作为参数传递给下一个componentDidUpdate()钩子函数中。所以此函数不能单独使用
	class ScrollingList extends React.Component {
  constructor(props) {
    super(props);
    this.listRef = React.createRef();
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    // 我们是否在 list 中添加新的 items ?
    // 捕获滚动​​位置以便我们稍后调整滚动位置。
    if (prevProps.list.length < this.props.list.length) {
      const list = this.listRef.current;
      return list.scrollHeight - list.scrollTop;
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    // 如果我们 snapshot 有值,说明我们刚刚添加了新的 items,
    // 调整滚动位置使得这些新 items 不会将旧的 items 推出视图。
    //(这里的 snapshot 是 getSnapshotBeforeUpdate 的返回值)
    if (snapshot !== null) {
      const list = this.listRef.current;
      list.scrollTop = list.scrollHeight - snapshot;
    }
  }

  render() {
    return (
      <div ref={this.listRef}>{/* ...contents... */}</div>
    );
  }
}

5. componentDidUpdate(prevProps,prevState,snapshot)

  • componentDidUpdate()会在更新后立即被调用,首次渲染不会被调用,主要用来与前一个状态作对比
	componentDidUpdate(prevProps) {
  // 典型用法(不要忘记比较 props):
  if (this.props.userID !== prevProps.userID) {
    this.fetchData(this.props.userID);
  }
}

它的第三个参数即为getSnapshotBeforeUpdate()传递过来的数据。否则此参数将为undefined

卸载阶段的钩子函数

1. componentWillUnmount()

  • componentWillUnmount() 会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅等.在此钩子函数中不应该调用setState(),因为该组件不会重新渲染

错误处理

1. static getDerivedStateFromError(error)

  • 此生命周期会在后代组件抛出错误后被调用。 它将抛出的错误作为参数,并返回一个值以更新 state
	class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // 更新 state 使下一次渲染可以显降级 UI
    return { hasError: true };
  }

  render() {
    if (this.state.hasError) {
      // 你可以渲染任何自定义的降级  UI
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children; 
  }
}

2. componentDidCatch(error,info)

  • 此生命周期在后代抛出错误后被调用。他有两个参数:
    1.error —— 抛出的错误
    2.info —— 带有componentStack key的对象,其中包含有关组件引发错误的栈信息。
	class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // 更新 state 使下一次渲染可以显示降级 UI
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    // "组件堆栈" 例子:
    //   in ComponentThatThrows (created by App)
    //   in ErrorBoundary (created by App)
    //   in div (created by App)
    //   in App
    logComponentStackToMyService(info.componentStack);
  }

  render() {
    if (this.state.hasError) {
      // 你可以渲染任何自定义的降级 UI
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children; 
  }
}
此外还有一些不常见的钩子函数本文并未提及,详情请参考:React.Component
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!