react中在componentDidMount生命周期函数中调用了多个this.setState报错

报错:超过最大更新深度。当组件在componentWillUpdate或componentDidUpdate中重复调用setState时,就会发生这种情况。React限制嵌套更新的数量,以防止无限循环。
在componetDidMount和componentDidUpdate中:
componentDidMount(): void {
const winW = document.documentElement.clientWidth || document.body.clientWidth;
const winH = document.documentElement.clientHeight || document.body.clientHeight;
const width = winW/2;
const height = winH/4;
const cx = winW/8;
const cy = winH/10;
this.setState({width,height,cx,cy})
if(this.props.pieName === 'dayElectric'){
var responece:object = FloorData.dayElectric.map((item:Electric,index:number)=>item)
}
if(this.props.pieName === 'monthElectric'){
var responece:object = FloorData.monthElectric.map((item:Electric,index:number)=>item)
}
if(this.props.pieName === 'yearElectric'){
var responece:object = FloorData.yearElectric.map((item:Electric,index:number)=>item)
}
}
componentDidUpdate(prevProps: Readonly<RouteComponentProps>, prevState: Readonly<{}>, snapshot?: any): void {
const winW = document.documentElement.clientWidth || document.body.clientWidth;
const winH = document.documentElement.clientHeight || document.body.clientHeight;
const width = winW/2;
const height = winH/4;
const cx = winW/14;
const cy = winH/14;
this.setState({width,height,cx,cy})
}
修改后:
// 会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用
static getDerivedStateFromProps(nextProps:RouteComponentProps<{type:string}>, prevState:any) {
var responeceDate:any[] =[];
const winW = document.documentElement.clientWidth || document.body.clientWidth;
const winH = document.documentElement.clientHeight || document.body.clientHeight;
const width = winW/2;
const height = winH/4;
const {type} = nextProps;
if(type === '0'){
responeceDate = FloorData.dayElectric
}else if(type === '1'){
responeceDate = FloorData.monthElectric
}else if(type === '2'){
responeceDate = FloorData.yearElectric
}
return {//返回一个对象来更新 state,如果返回 null则不更新任何内容。
data:responeceDate,
width,height
};
// return null;
}
componentDidMount()
会在组件挂载后(插入DOM树中) 立即调用。如需通过网络请求获取数据,此处是实例化请求的好地方
你可以在 componentDidMount() 里直接调用 setState()。它将触发额外渲染,但此渲染会发生在浏览器更新屏幕之前。如此保证了即使在 render() 两次调用的情况下,用户也不会看到中间状态。请谨慎使用该模式,因为它会导致性能问题。
componentDidUpdate()
会在更新后会被立即调用。首次渲染不会执行此方法。
你也可以在 componentDidUpdate() 中直接调用 setState(),但请注意它必须被包裹在一个条件语句里,正如上述的例子那样进行处理,否则会导致死循环。它还会导致额外的重新渲染,虽然用户不可见,但会影响组件性能。
conponentWillUnmount()
会在组件卸载及销毁之前调用。在此方法中执行必要的清理操作,例如清除timer,取消网络请求或清除在componentDidMount() 中创建的订阅等。
componentWillUnMount() 中不应该调用setState(),因为该组件将永远不会重新渲染,组件实例卸载后将永远不会再挂载它。
static getDerivedStateFromProps(prps,state)
会因为props和state发生了改变而调用,会在初始化挂载及后续更新时都会被调用,它应返回一个对象来更新state,如果返回null则不更新任何内容。
用例:即state的值在任何时候都取决于props
例子:
state = {
data:[],
width:0,
height:0,
pieName:'dayElectric',
}
componentDidMount(): void {
console.log('componentDidMount')
}
// 会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用
static getDerivedStateFromProps(nextProps:RouteComponentProps<{type:string}>, prevState:any) {
console.log('getDerivedStateFromProps',nextProps)
var responeceDate:any[] =[];
const winW = document.documentElement.clientWidth || document.body.clientWidth;
const winH = document.documentElement.clientHeight || document.body.clientHeight;
const width = winW/2;
const height = winH/4;
const {type} = nextProps;
if(type === '0'){
responeceDate = FloorData.dayElectric
}else if(type === '1'){
responeceDate = FloorData.monthElectric
}else if(type === '2'){
responeceDate = FloorData.yearElectric
}
return {//返回一个对象来更新 state,如果返回 null则不更新任何内容。
data:responeceDate,
width,height
};
// return null;
}
componentDidUpdate(prevProps: Readonly<RouteComponentProps<{ type: string }>>, prevState: Readonly<{}>, snapshot?: any): void {
console.log('componentDidUpdate')
}
componentWillUnmount(): void {
console.log('componentWillUnmount')
}
运行结果:
//第一次: getDerivedStateFromProps componentDidMount
//第二次更新:getDerivedStateFromProps componentDidUpdate
shouldComponentUpdate(nextProps,nextState)
根据 shouldComponentUpdate() 的返回值,判断 React 组件的输出是否受当前 state 或 props 更改的影响。默认行为是 state 每次发生变化组件都会重新渲染。
此方法仅作为性能优化的方式而存在。不要企图依靠此方法来“阻止”渲染,因为这可能会产生 bug。你应该考虑使用内置的 PureComponent 组件,而不是手动编写 shouldComponentUpdate()。PureComponent 会对 props 和 state 进行浅层比较,并减少了跳过必要更新的可能性。
在class组件中写了getDerivedStateFromProps()生命周期函数就不能同时写componentWillMount和componentWillUpdate生命周期,不然会报以下错误:
警告:使用新的组件api的组件将不会调用不安全的遗留生命周期
这是因为React16.8及以上版本将getDerivedStateFromProps该生命周期函数代替了componentWillMount和componentWillUpdate生命周期
更多推荐
所有评论(0)