您的位置:首页 > Web前端 > React

React组件的生命周期理解

2020-03-08 16:19 531 查看

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
  • 点赞 1
  • 收藏
  • 分享
  • 文章举报
beacon... 发布了2 篇原创文章 · 获赞 2 · 访问量 33 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: