我试图让这段代码作为一个“增量”游戏工作,其中的选项将在一些积分后显示,但我收到以下警告(仅一次):
index.js:2178 警告:无法在现有状态转换期间更新(例如在render
其他组件的构造函数中)。Render 方法应该是 props 和 state 的纯函数;构造函数的副作用是一种反模式,但可以移至componentWillMount
.
import React, { Component } from 'react';
import { Grid, Button } from "semantic-ui-react";
class EventDashboard extends Component {
constructor(props) {
super(props)
this.state={
credits: 0,
newOption: false,
newOptionDirty: false,
}
this.addCredits = this.addCredits.bind(this)
this.renderNewOption = this.renderNewOption.bind(this)
this.intervalID = null;
}
addCredits() {
this.setState((previousState) => ({
credits: previousState.credits + 1
}))
}
componentDidMount() {
this.intervalID = setInterval(() => {
this.addCredits()
}, 1000)
}
componentWillUnmount() {
clearInterval(this.intervalID);
}
renderNewOption() {
if(this.state.credits === 5 && !this.state.newOptionDirty) {
// the warning happens here
this.setState(() =>({
newOptionDirty: true
}))
}
if(this.state.newOptionDirty) {
return(
<div>
<Button> Add new feature </Button>
</div>
)
} else {
return (
<div>no options until 5 credits</div>
)
}
}
render() {
return (
<Grid>
<Grid.Column width={10}>
<Button
onClick={this.addCredits}
>AddCredits</Button>
{this.renderNewOption()}
</Grid.Column>
<Grid.Column width={6}>
<h1>Credits</h1>
<h2>{this.state.credits}</h2>
</Grid.Column>
</Grid>
)
}
}
export default EventDashboard
尽管有此警告,但一切正常。
我缺少什么好的做法?
问题确实在于您的renderNewOption()
方法以及您如何使用它。
您正在调用renderNewOption()
from render()
,这很糟糕,因为您正在其中执行 a setState()
。请记住,无论何时setState()
更新状态并触发新的渲染。因此,在setState()
里面render()
会创建一个无限循环,因为渲染函数会不断调用自己。
在这种特殊情况下,您实际上不会得到无限循环,因为您有一个if
-case 可以防止这种情况发生,但是您的组件将第一次运行它(when newOptionDirty
is still false
)。发生这种情况时,您的组件尚未安装,因为在调用render()
此特定之前从未完成setState()
。
TL;DR:永远不要setState()
在渲染过程中调用。
试试这个:
componentDidMount() {
setInterval(() => {
this.addCredits()
}, 1000);
}
addCredits() {
this.setState((previousState) => ({
credits: previousState.credits + 1
});
}
renderNewOption() {
if(this.state.credits >= 5) {
return(
<div>
<Button> Add new feature </Button>
</div>
)
} else {
return (
<div>no options until 5 credits</div>
)
}
}
我们不需要(也不应该)在渲染中创建一些新的状态变量。我们只关心是否credits
等于5
或不等于。
根据它的值,我们返回适当的 React 元素(按钮或无按钮)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句