The setState()
hook in React is asynchronous. This can lead us to some undesired results as we will see in the folowing example.
The problem
A friend asked me to help him with the following code:
// ✋🛑 Don't do this
const App = () => {
const [query, setQuery] = useState('')
const [jokes, setJokes] = useState([])
const search = (e) => {
setQuery(e.target.value)
fetch('https://icanhazdadjoke.com/search?term=' + query, {
headers: { Accept: 'application/json' }
})
.then(resp => resp.json())
.then(json => {
console.log(json)
setJokes(json.results)
})
}
return (<div>
<input value={query} onChange={search} />
<p>Found {jokes.length} jokes about "<b>{query}</b>"!</p>
</div>);
}
The idea was simple. Search in an API what the user typed in the text input.
However, the searchterm
was always one character behind what was typed in the input.
The solution
This happens because React setState()
is asynchronous.
One reason why setState()
is async is to batch mutiple setState() calls for performance gains.
For this example it would make sense to have something like this:
setState().then( /* do the fetch here */)
While the above solution is not possible what we can do is to monitor the query value with the useEffect() hook.
When the state value changes we will fetch new data:
// 👍 Do this instead
const App = () => {
const [query, setQuery] = useState('')
const [jokes, setJokes] = useState([])
useEffect(() => {
fetch('https://icanhazdadjoke.com/search?term=' + query, {
headers: { Accept: 'application/json' }
})
.then(resp => resp.json())
.then(json => {
console.log(json)
setJokes(json.results)
})
}, [query])
const search = (e) => setQuery(e.target.value)
return (<div>
<input value={query} onChange={search} />
<p>Found {jokes.length} jokes about "<b>{query}</b>"!</p>
</div>);
}
This will make sure that our code runs in perfect sync with the state variables.
You can check out the full code example on my GitHub and the running example here.
📖 50 Javascript, React and NextJs Projects
Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects with project briefs and wireframes! Choose from 8 project categories and get started right away.
📖 50 Javascript, React and NextJs Projects
Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects with project briefs and wireframes! Choose from 8 project categories and get started right away.