React生命周期-踩坑记_10

React生命周期

生命周期概览

生命周期的状态

组件的生命周期可分红三个状态:html

  • Mounting:已插入真实 DOM
  • Updating:正在被从新渲
  • Unmounting:已移出真实 DOM
  • componentWillMount 在渲染前调用,在客户端也在服务端。

生命周期介绍

componentDidMount :

在第一次渲染后调用,只在客户端。以后组件已经生成了对应的DOM结构,能够经过this.getDOMNode()来进行访问。 若是你想和其余JavaScript框架一块儿使用,能够在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操做(防止异步操做阻塞UI)。react

componentWillReceiveProps

在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。浏览器

shouldComponentUpdate

返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。
能够在你确认不须要更新组件时使用。网络

componentWillUpdate

在组件接收到新的props或者state但尚未render时被调用。在初始化时不会被调用。框架

componentDidUpdate

在组件完成更新后当即调用。在初始化时不会被调用。异步

componentWillUnmount

在组件从 DOM 中移除以前马上被调用。async

代码示意

class Content extends React.Component {
  componentWillMount() {
      console.log('Component WILL MOUNT!')
  }
  componentDidMount() {
       console.log('Component DID MOUNT!')
  }
  componentWillReceiveProps(newProps) {
        console.log('Component WILL RECEIVE PROPS!')
  }
  shouldComponentUpdate(newProps, newState) {
        return true;
  }
  componentWillUpdate(nextProps, nextState) {
        console.log('Component WILL UPDATE!');
  }
  componentDidUpdate(prevProps, prevState) {
        console.log('Component DID UPDATE!')
  }
  componentWillUnmount() {
         console.log('Component WILL UNMOUNT!')
  }

React16.3生命周期

安装

在建立组件的实例并将其插入DOM时,将按如下顺序调用这些方法:函数

constructor()

React组件的构造函数在安装以前被调用。在实现React.Component子类的构造函数时,应该super(props)在任何其余语句以前调用。不然,this.props将在构造函数中未定义,这可能致使错误。工具

一般,在React中,构造函数仅用于两个目的:性能

经过分配对象来初始化本地状态this.state。
将事件处理程序方法绑定到实例。
不该该打电话setState()给constructor()。相反,若是您的组件须要使用本地状态,请直接在构造函数中指定初始状态this.state。

构造函数是his.state直接分配的惟一位置。在全部其余方法中,须要使用this.setState()。

static getDerivedStateFromProps()

getDerivedStateFromProps在调用render方法以前调用,不管是在初始安装仍是后续更新。它应该返回一个更新状态的对象,或者返回null以不更新任何状态。

render()

render()方法是类组件中惟一必需的方法。

调用时,它应检查this.props并this.state返回如下类型之一:

  • React elements。一般经过JSX建立。
  • Arrays and fragments。让您从渲染中返回多个元素。有关更多详细信息,请参阅片断文档。
  • Portals。
  • 字符串和数字。它们在DOM中呈现为文本节点。
  • 布尔或null。什么都没有。

该render()函数应该无状态的,这意味着它不会修改组件状态,每次调用时都返回相同的结果,而且它不直接与浏览器交互。

若是您须要与浏览器进行交互,请执行componentDidMount()或其余生命周期方法。保持render()纯粹使组件更容易思考。

若是shouldComponentUpdate()返回false,则render()不会被调用

componentDidMount()

  • componentDidMount()在安装组件(插入树中)后当即调用。须要DOM节点的初始化应该放在这里。若是须要从远程端点加载数据,这是实例化网络请求的好地方。
  • 此方法是设置任何订阅的好地方。若是您这样作,请不要忘记取消订阅componentWillUnmount()。
  • 您能够在componentDidMount()当即使用this.setState()。它将触发额外的渲染,但它将在浏览器更新屏幕以前发生。这保证即便render()在这种状况下将被调用两次,用户也不会看到中间状态。请谨慎使用此模式,由于它一般会致使性能问题。在大多数状况下,您应该可以分配初始状态constructor()。可是,当您须要在渲染依赖于其大小或位置的东西以前测量DOM节点时,可能须要对模态和工具提示等状况进行处理。

这些方法被认为是遗留的,应该在新代码中避免它们:

UNSAFE_componentWillMount()

更新

props or state 的更改可能致使更新。从新渲染组件时,将按如下顺序调用这些方法:

static getDerivedStateFromProps()

render()

getSnapshotBeforeUpdate()

getSnapshotBeforeUpdate(prevProps, prevState)

getSnapshotBeforeUpdate()在最近呈现的输出被提交到例如DOM以前调用。它使得组件能够在可能更改以前从DOM捕获一些信息(例如滚动位置)。今生命周期返回的任何值都将做为参数传递给componentDidUpdate()。

此用例并不常见,但它可能出如今须要以特殊方式处理滚动位置的聊天线程等UI中。

官网的例子

class ScrollingList extends React.Component {
  constructor(props) {
    super(props);
    this.listRef = React.createRef();
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    // Are we adding new items to the list?
    // Capture the scroll position so we can adjust scroll later.
    if (prevProps.list.length < this.props.list.length) {
      const list = this.listRef.current;
      return list.scrollHeight - list.scrollTop;
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    // If we have a snapshot value, we've just added new items.
    // Adjust scroll so these new items don't push the old ones out of view.
    // (snapshot here is the value returned from getSnapshotBeforeUpdate)
    if (snapshot !== null) {
      const list = this.listRef.current;
      list.scrollTop = list.scrollHeight - snapshot;
    }
  }

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

componentDidUpdate()

componentDidUpdate()更新发生后当即调用。初始渲染不会调用此方法。

将此做为在更新组件时对DOM进行操做的机会。只要您将当前道具与以前的道具进行比较(例如,若是道具未更改,则可能不须要网络请求),这也是进行网络请求的好地方。

componentDidUpdate(prevProps) {
  // Typical usage (don't forget to compare props):
  if (this.props.userID !== prevProps.userID) {
    this.fetchData(this.props.userID);
  }
}

componentDidUpdate()但要注意,必须在一个条件下被包裹就像上面的例子中,不然会致使无限循环。它还会致使额外的从新渲染,虽然用户不可见,但会影响组件性能。

componentDidUpdate():若是shouldComponentUpdate()返回false,则不会被调用。

这些方法被认为是遗留的,您应该在新代码中避免它们:

UNSAFE_componentWillUpdate()

UNSAFE_componentWillReceiveProps()

卸载

从DOM中删除组件时调用此方法:

componentWillUnmount()

componentWillUnmount()在卸载和销毁组件以前当即调用。在此方法中执行任何须要的清理,例如使计时器无效,取消网络请求或清除在其中建立的任何订阅componentDidMount()。

不该该调用setState(),componentWillUnmount()由于组件永远不会被从新呈现。卸载组件实例后,将永远不会再次安装它。

错误处理

在渲染期间,生命周期方法或任何子组件的构造函数中发生错误时,将调用这些方法。

static getDerivedStateFromError()

static getDerivedStateFromError(error)

在后代组件抛出错误后调用今生命周期。它接收做为参数抛出的错误,并应返回值以更新状态。

componentDidCatch()

componentDidCatch(error, info)

在后代组件抛出错误后调用今生命周期。它接收两个参数:

error - 抛出的错误。
info- componentStack包含键的对象,其中包含有关哪一个组件引起错误的信息。

若是发生错误,能够componentDidCatch()经过调用呈现回退UI setState,但在未来的版本中将不推荐使用。使用static getDerivedStateFromError()处理回退,而不是渲染。

componentDidCatch()在“提交”阶段被调用,所以容许反作用。它应该用于记录错误之类的事情:

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI.
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    // Example "componentStack":
    //   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) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children; 
  }
}

image

image

http://projects.wojtekmaj.pl/...

https://reactjs.org/blog/2018...

https://reactjs.org/docs/reac...

相关文章
相关标签/搜索