My React client app should guess the secret number between 1 and 10 000. Here is my code:
import axios from 'axios';
import React, { Component } from 'react';
class GuessEngine extends Component {
constructor(props) {
super(props);
this.state = {
number: null,
result: null,
};
}
componentDidMount() {
const firstGuess = 5000;
axios
.post('http://localhost:3001/number', {
isNumber: firstGuess,
})
.then(response => {
const { resultCode } = response.data;
this.setState({ number: firstGuess });
this.setState({ result: resultCode });
})
.catch(error => console.log(error));
}
componentDidUpdate(prevProps, prevState) {
if (prevState !== this.state) {
if (this.state.result === 'lower') {
const newNumber = this.state.number - 1;
axios.post('http://localhost:3001/number', {
isNumber: newNumber,
});
this.setState({ number: newNumber });
}
if (this.state.result === 'higher') {
const newNumber = this.state.number + 1;
axios.post('http://localhost:3001/number', {
isNumber: newNumber,
});
this.setState({ number: newNumber });
}
if (this.state.result === 'success') {
console.log(`Success! The secret number is ${this.state.number}!`);
}
}
}
render() {
return <div>Test</div>;
}
}
export default GuessEngine;
And I'm getting an error like this:
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.
So if I can't use componentDidUpdate
like this, what is the proper way to use React Lifecycle Hooks
to make it work?
My app has sent 1011 request and than it crashed.
So using @John_Ruddell answer I came up with this solution:
componentDidUpdate() {
if (this.state.result !== 'success') {
if (this.state.result === 'lower') {
const newNumber = this.state.number - 1;
axios
.post('http://localhost:3001/number', {
isNumber: newNumber,
})
.then(response => {
const { resultCode } = response.data;
this.setState({ result: resultCode, number: newNumber });
});
} else if (this.state.result === 'higher') {
const newNumber = this.state.number + 1;
axios
.post('http://localhost:3001/number', {
isNumber: newNumber,
})
.then(response => {
const { resultCode } = response.data;
this.setState({ result: resultCode, number: newNumber });
});
}
} else if (this.state.result === 'success') {
console.log(`Success! The secret number is ${this.state.number}!`);
} else {
console.log(`Sorry! Some errors occured!`);
}
}
This code does not compares this.state.number !== prevState.number
, but only in this way I forced it to work
you are setting state every time the component did update is firing.. instead of waiting for a callback from the request to see if its lower or higher
also you should put the logic of state transitions into better conditionals
const nextNum = { lower: -1, higher: 1 } // simple mapping of the next guess so you can reduce amount of code
componentDidUpdate(prevProps, prevState) {
if (this.state.result && this.state.number !== prevState.number) {
if (nextNum[this.state.result]) {
// make request with the number
const newNumber = nextNum[this.state.result]
axios.post('http://localhost:3001/number', {
isNumber: newNumber,
}).then(response => {
const { resultCode } = response.data;
this.setState({result: resultCode, number: newNumber})
}).catch(error => console.log(error));
} else if (this.state.result === 'success') {
console.log(`Success! The secret number is ${this.state.number}!`);
}
}
}
Note the key thing here is you should only setState AFTER the request comes back.. or else you will just endlessly setState.. because this.state.result
will never be updated to be success
setState
will lead to the update so your componentDidUpdate
will be called over and over again:
componentDidUpdate(prevProps, prevState) {
// after each update this will be true and further runing another updates
if (prevState !== this.state) {
}
}
You need better logic to decipher whether you need to do an update or not. Meaning at some point componentDidUpdate
should not do anything.
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.