[英]Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate
[英]Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate
已经有人问了这个问题,但他们几乎是由相同的原因引起的(原地触发回调,例如<div onClick={this.handleClick()}></div>
)。 然而,这并没有发生在我身上,但我得到了同样的错误。
PS 一些 util 函数是在幕后定义的。
// Parent
export default class SearchArea extends React.Component {
constructor(props) {
super(props);
this.state = {
data: {
update: '',
confirmed: '',
recovered: '',
deaths: ''
},
showDashboard: false
}
this.setCountryData = this.setCountryData.bind(this);
this.showDashboard = this.showDashboard.bind(this);
}
setCountryData(data) {
console.log(data);
this.setState({
data: {
update: data.lastUpdate,
confirmed: data.confirmed,
recovered: data.recovered,
deaths: data.deaths
}
});
}
showDashboard(toggle) {
this.setState({ showDashboard: toggle })
}
render() {
return (
<div>
<Dropdown onSetCountryData={this.setCountryData} onShowDashboard={this.showDashboard} />
<Dashboard data={this.state.data} visible={this.state.showDashboard} />
</div>
)
}
}
// Sibling1
class Dropdown extends React.Component {
constructor(props) {
super(props);
this.state = {
countries: [],
currentCountry: ''
};
this.handleClick = this.handleClick.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleClick() {
const showCountryData = Fetch(newFetchCountry).showJSONData;
showCountryData().then(res => {
const data = res[0];
this.passCountryData(data);
})
this.passToggleDashboard(true);
}
handleChange(e) {
this.setState({ currentCountry: e.target.value, });
this.passToggleDashboard(false);
}
passCountryData(data) {
this.props.onSetCountryData(data);
}
passToggleDashboard(toggle) {
this.props.onShowDashboard(toggle);
}
componentDidMount() {
let timer = setTimeout(() => {
const showCountryList = Fetch(fetchCountryList).showJSONData;
showCountryList().then(res => {
const data = res.map(country => country);
this.setState({ countries: data })
});
clearTimeout(timer);
}, 2000)
}
render() {
return (
<section className="dropdown-area">
<div className="dropdown">
<label htmlFor="country">Select country:</label>
<input list="countries" name="country" id="country" onChange={this.handleChange} />
<datalist id="countries" required>
{this.state.countries.length ?
this.state.countries.map(country => <option key={country.name}>{country.name}</option>) :
<option disabled>Loading</option>}
</datalist>
</div>
<button className="comp" onClick={this.handleClick}>Search</button>
</section>
)
}
}
// Sibling2
class Dashboard extends React.Component {
constructor(props) {
super(props);
this.state = {
data: {
update: '',
confirmed: '',
recovered: '',
deaths: ''
}
};
}
componentDidMount() {
if (!('data' in this.props)) {
const showWorldData = Fetch(fetchWorld).showJSONData;
showWorldData().then(res => {
const data = res[0];
this.setState({
data: {
update: data.lastUpdate,
confirmed: data.confirmed,
recovered: data.recovered,
deaths: data.deaths
}
});
});
}
}
componentDidUpdate() { // Error here!!!
if ('data' in this.props) {
const data = this.props.data;
this.setState({
data: {
update: data.lastUpdate,
confirmed: data.confirmed,
recovered: data.recovered,
deaths: data.deaths
}
});
}
}
render() {
const visibility = {
visibility: 'visible' in this.props && !this.props.visible ? 'hidden' : 'visible'
};
return (
<section className="dashboard-area" style={visibility}>
<span>Last Update: {this.state.data.update || 'Loading...'}</span>
<div className="dashboards">
<DashboardItem num={this.state.data.confirmed} type="Confirmed" />
<DashboardItem num={this.state.data.recovered} type="Recovered" />
<DashboardItem num={this.state.data.deaths} type="Deaths" />
</div>
</section>
)
}
}
class DashboardItem extends React.Component {
render() {
return (
<div className="dashboard">{this.props.type}: <br /><span>{this.props.num || 'Loading...'}</span></div>
)
}
}
错误出现在Dashboard
组件中的componentDidMount()
中。 我找不到无限触发重新渲染的位置。
setState 方法会重复更新组件,因为每次'data' in this.props
等于true
时,您都会调用setState
并且调用 setState 默认会更新组件,并且componentDidUpdate
将再次检查'data' in this.props
等于true
等
您应该为if
语句制定严格的条件
尝试这个
componentDidUpdate(prevProps, prevState) {
if ('data' in this.props && this.props.data !== prevProps.data) {
const data = this.props.data;
this.setState({
data: {
update: data.lastUpdate,
confirmed: data.confirmed,
recovered: data.recovered,
deaths: data.deaths
}
});
}
}
您的问题源于派生的 state: state 它依赖于道具并且是反应中的反模式。
这将告诉你更多关于它的信息:
https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
有一些变通方法,但建议您改用重组数据流。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.