简体   繁体   English

错误:超过最大更新深度。 当组件在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState 时,可能会发生这种情况

[英]Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate

There's already some people asking this question but they are almost caused by the same reason (fire the callback in situ eg <div onClick={this.handleClick()}></div> ).已经有人问了这个问题,但他们几乎是由相同的原因引起的(原地触发回调,例如<div onClick={this.handleClick()}></div> )。 However this doesn't happen to me but I got the same error.然而,这并没有发生在我身上,但我得到了同样的错误。

PS Some util functions are defined behind the scene. 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>
        )
    }
}

Error is in the componentDidMount() in the Dashboard component.错误出现在Dashboard组件中的componentDidMount()中。 I can't find where I fired the re-render infinitely.我找不到无限触发重新渲染的位置。

The setState method is repeatedly updating the component because every time the 'data' in this.props equals to true you're calling setState and calling setState will by default update the component and componentDidUpdate will check again if 'data' in this.props equals to true and so setState 方法会重复更新组件,因为每次'data' in this.props等于true时,您都会调用setState并且调用 setState 默认会更新组件,并且componentDidUpdate将再次检查'data' in this.props等于true

You should make strict conditions for if statement您应该为if语句制定严格的条件

try this尝试这个

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
            }
        });
    }
}

Your issue stems from derived state: state which is made dependent on props and is an anti-pattern in react.您的问题源于派生的 state: state 它依赖于道具并且是反应中的反模式。

This will tell you more about it:这将告诉你更多关于它的信息:

https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html

There are some work arounds, but its recommended you instead restructure your data flow.有一些变通方法,但建议您改用重组数据流。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 超出最大更新深度。 当组件在componentWillUpdate或componentDidUpdate中重复调用setState时,可能会发生这种情况 - Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate 错误“超出最大更新深度。当组件在 useEffect 中调用 setState 时可能会发生这种情况” - Error "Maximum update depth exceeded. This can happen when a component calls setState inside useEffect" 不变违反:最大更新深度..当组件重复调用componentWillUpdate或componentDidUpdate内部的setState时 - Invariant Violation: Maximum update depth..when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate 超过最大更新深度。 当组件在 useEffect 中调用 setState 时,可能会发生这种情况, - Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, 未捕获的错误:当组件在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState 时,可能会发生这种情况 - Uncaught Error: This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate 如何修复“超出最大更新深度。在 componentWillUpdate 或 componentDidUpdate 中调用 setState。” 反应错误? - How to fix “Maximum update depth exceeded.calls setState inside componentWillUpdate or componentDidUpdate.” error in react? 错误:超过最大更新深度。 setState 抛出错误 - Error: Maximum update depth exceeded. setState throws error 在componentWillUpdate或componentDidUpdate中反复调用setState? - Repeatedly calling setState inside componentWillUpdate or componentDidUpdate? 错误:超过最大更新深度。 在反应 - Error: Maximum update depth exceeded. in react ComponentDidUpdate - 超出最大更新深度 - 错误 - ComponentDidUpdate - Maximum update depth exceeded - Error
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM