简体   繁体   中英

Calling functions in componentDidUpdate. Error: React limits the number of nested updates

When I get from api response object:

timeLoad =  {
  date: "2019-07-07 12:38:08+00",
  pend: true
}

I want to set:

this.setState({
  time: this.props.timeLoad.second * 1000
})

When I get from api response object:

timeLoad =  {
        date: null,
        pend: false
    }

I want to call function start().


componentDidUpdate(previousProps, previousState) {
    if (previousProps.timeLoad !== this.timeLoad) {
        if(this.props.timeLoad && this.props.timeLoad.date && 
         this.props.timeLoad.second) {
            this.setState({
                time: this.props.timeLoad.second * 1000
            })
        } else {
            this.setState({
                time: 0
            })
        }
    }
}

Above code it works, but when I added:

if (this.props.timeLoad && !this.props.timeLoad.date && !this.props.timeLoad.pend) {
     this.start ();
}

I have error:

Uncaught Invariant Violation: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

How can I fix it?

I tried deep comparison with the property's value: (previousProps.timeLoad.second !== this.timeLoad.second) but I have error:

Cannot read property 'second' of null.

Not every object has the 'second' property or has 'null' property.

class Watch extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      timerOn: false,
      timerStart: 0,
      time: 0
    }
   }

    componentDidUpdate(previousProps, previousState) {
        if (previousProps.timeLoad !== this.timeLoad) {
            if(this.props.timeLoad && this.props.timeLoad.second && 
             this.props.timeLoad.second) {
                this.setState({
                    time: this.props.timeLoad.second * 1000
                })
            } else {
                this.setState({
                    time: 0
                })
            }
        }

        if(this.props.timeLoad  && !this.props.timeLoad.date && !this.props.timeLoad.pend){
            this.start();
        }
    }


    start = () => {
        this.setState({
            timerOn: true,
            time: this.state.time,
            timerStart: Date.now() - this.state.time
        });
        this.timer = setInterval(() => {
            this.setState({
                time: Date.now() - this.state.time
            });
        }, 10);

        const url = `https://app/api/v1/asset/{id}`

        axios({ 
            method: 'post', 
            url, 
            data: this.item, 
            headers: { Authorization: `Bearer ${token}` }, 
            }) 
            .then(res => { 
                this.setState({
                    startItem: res.data.item,
                })
            }).catch(err => { 
                console.log(err); 
            });
     };

        render() {
            return ( 
                <button className="play" onClick={this.start}>
                    Button
                </button>
            );
        }
 }

This is a shallow comparison:

if (previousProps.timeLoad !== this.timeLoad)

Will always return true (different objects) and update the state every time, this is what is causing the infinite loop. Try a deep comparison with the property's value:

if (previousProps.timeLoad.seconds !== this.timeLoad.seconds)

I solved it:

I had to put

if(this.props.timeLoad  && !this.props.timeLoad.date && 
    !this.props.timeLoad.pend){
       this.start();
}

inside if (previousProps.timeLoad !== this.timeLoad) {}

 componentDidUpdate(previousProps, previousState) {
        if (previousProps.timeLoad !== this.timeLoad) {
            if(this.props.timeLoad && this.props.timeLoad.second && 
             this.props.timeLoad.second) {
                this.setState({
                    time: this.props.timeLoad.second * 1000
                })
            } else {
                this.setState({
                    time: 0
                })
            }

            if(this.props.timeLoad  && !this.props.timeLoad.date && 
              !this.props.timeLoad.pend){
                 this.start();
             }
        }

    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM