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
来源:CSDN
作者:weixin_45374484
链接:https://blog.csdn.net/weixin_45374484/article/details/104456589