DEV Community

Cover image for How to fix React Hook warnings for async functions in useEffect
collegewap
collegewap

Posted on • Originally published at codingdeft.com

How to fix React Hook warnings for async functions in useEffect

When you try to execute an async activity inside the React useEffect hook, you might have seen the following warnings:

Effect callbacks are synchronous to prevent race conditions. Put the async function inside:

return warning

useEffect function must return a cleanup function or nothing

async warning

Consider the following code:

import { useEffect, useState } from "react"

function App() {
  const [posts, setPosts] = useState([])

  useEffect(async () => {
    try {
      const response = await fetch(`https://jsonplaceholder.typicode.com/posts`)
      const data = await response.json()
      setPosts(data)
    } catch (e) {
      console.error(e)
    }
  }, [])

  return (
    <div className="App">
      <ul>
        {posts.map(post => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  )
}

export default App
Enter fullscreen mode Exit fullscreen mode

Here, we are passing async function to the useEffect hook. As you may be aware, async functions return a Promise. However, useEffect expects the function to either return nothing or a clean up function. Hence reacts throws this warning.

There are 2 ways to fix this.

Moving async call to another function

We can define another function inside the useEffect and call it inside the useEffect as shown below:

import { useEffect, useState } from "react"

function App() {
  const [posts, setPosts] = useState([])

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(
          `https://jsonplaceholder.typicode.com/posts`
        )
        const data = await response.json()
        setPosts(data)
      } catch (e) {
        console.error(e)
      }
    }
    fetchData()
  }, [])
  return (
    <div className="App">
      <ul>
        {posts.map(post => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  )
}

export default App
Enter fullscreen mode Exit fullscreen mode

Now the function passed to useEffect returns nothing, thus by fulfilling the condition.

Also, you could prevent the race condition by cancelling previous requests.

Using .then() chaining

Instead of using async await syntax, we can use .then() to resolve the promise:

import { useEffect, useState } from "react"

function App() {
  const [posts, setPosts] = useState([])

  useEffect(() => {
    fetch(`https://jsonplaceholder.typicode.com/posts`)
      .then(response => response.json())
      .then(data => {
        setPosts(data)
      })
      .catch(e => {
        console.log(e)
      })
  }, [])
  return (
    <div className="App">
      <ul>
        {posts.map(post => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  )
}

export default App
Enter fullscreen mode Exit fullscreen mode

Now if you run the code, you should not be seeing the warning anymore.

Top comments (0)