Is setState in React asyc? A practical example

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.
Is setState in React asyc? A practical example

The solution

This happens because React setState() is asynchronous.
Is setState in React asyc? A practical example

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.


Leave a Reply

Your email address will not be published. Required fields are marked *

Home Screencasts Best of Newsletter Search X

📖 50 Javascript, React and NextJs Projects

Hi friend! Before you go, just wanted to let you know about the 50 Javascript, React and NextJs Projects FREE ebook.

One of the best ways to learn is by doing the work. Choose from 8 project categories and get started right away:

  • Business & Real-World
  • Games & Puzzles
  • Fun & Interesting
  • Tools & Libraries
  • Personal & Portfolio
  • Project Add-Ons
  • Productivity
  • Clones

Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects complete with project briefs and wireframes!

Keep building and level up! Get all projects as an ebook right to your inbox!

X