Staples Team Supervisor/Software Engineering Graduate of @flatiron-school
Published Jun 08, 2020
When updating state in a component you may end up in a situation where your using setState
to store the data but need to execute some block of code only after the state is updated and not before. This can you send you into a infinite loop of sending requests, updating the state, reloading the component because of the state change and then starting the whole process over again or unwanted behavior like needing to perform the same action twice to get a desired result. Timing can be everything in certain situations and this is why React’s setState
method has a convenient callback option built into it.
You have the option of adding a callback to any setState
call by passing in a second argument to the function. This is a example of a class component does not use the callback. What happens is that unwanted behavior that I was talking about, can you guess what would happen when you entered in a age of 26 for the first time?
import React, { Component } from 'react';
class App extends Component {
constructor(props) {
super(props);
this.state = {
age: 0,
};
}
updateAge = (value) => {
this.setState({ age: value});
this.checkAge;
};
checkAge = () => {
const { age } = this.state;
if (age !== 0 && age >= 21) {
// Make API call
} else {
// Show message that your not old enough yet kiddo
}
};
render() {
const { age } = this.state;
return (
<div>
<p>Beer Suggestor</p>
<input
type="number"
value={age}
onChange={e => this.updateAge(e.target.value)}
/>
</div>
);
}
}
export default App;
This is a simple example where you are setting a new state then running a method to check the new state and make a api request depending on the state. If you guessed that the API call would run when you put in a age of 26 the first time then you would be wrong. This is because the setState
method is asynchronous and it has not finished running by the time the checkAge
function is checking the state so the first time you change the age it will see the value of this.state.age
as equal to 0. If you changed the age a second time it would then see the previously input value of 26 and not the second age input which should be set as the newly set state. This is where the callback functionality comes in handy. If you where to change the code like the example below then you would get the desired result where when you change the age value the first time it would make the API request (given the age is over 21);
import React, { Component } from 'react';
class App extends Component {
constructor(props) {
super(props);
this.state = {
age: 0,
};
}
// this.checkAge is passed as the callback to setState
updateAge = (value) => {
this.setState({ age: value}, this.checkAge);
};
checkAge = () => {
const { age } = this.state;
if (age !== 0 && age >= 21) {
// Make API call to /beer
} else {
// Show message that your not old enough yet kiddo
}
};
render() {
const { age } = this.state;
return (
<div>
<p>Drinking Age Checker</p>
<input
type="number"
value={age}
onChange={e => this.updateAge(e.target.value)}
/>
</div>
);
}
}
export default App;
This is only a simple example of one use case for the setState callback functionality, I have set up a codesandbox.io with code that makes a request to a news API and has a search component that will make an additional request to the API using a controlled component so it uses the callback to make the subsequent request after the search term is submitted. Feel free to check it out here and play around with the code. I have included a API key you can use so you don’t have to set up your own account.
** NOTE: For some reason the request to API is not working on codesandbox.io, possibly as some sort of security precaution but if you run the code locally on your system it should work just fine **