Skip to content
react

How to fix React Hook warnings for async functions in useEffect

Dec 21, 2021Abhishek EH2 Min Read
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:

App.js
1import { useEffect, useState } from "react"
2
3function App() {
4 const [posts, setPosts] = useState([])
5
6 useEffect(async () => {
7 try {
8 const response = await fetch(`https://jsonplaceholder.typicode.com/posts`)
9 const data = await response.json()
10 setPosts(data)
11 } catch (e) {
12 console.error(e)
13 }
14 }, [])
15
16 return (
17 <div className="App">
18 <ul>
19 {posts.map(post => (
20 <li key={post.id}>{post.title}</li>
21 ))}
22 </ul>
23 </div>
24 )
25}
26
27export default App

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:

App.js
1import { useEffect, useState } from "react"
2
3function App() {
4 const [posts, setPosts] = useState([])
5
6 useEffect(() => {
7 const fetchData = async () => {
8 try {
9 const response = await fetch(
10 `https://jsonplaceholder.typicode.com/posts`
11 )
12 const data = await response.json()
13 setPosts(data)
14 } catch (e) {
15 console.error(e)
16 }
17 }
18 fetchData()
19 }, [])
20 return (
21 <div className="App">
22 <ul>
23 {posts.map(post => (
24 <li key={post.id}>{post.title}</li>
25 ))}
26 </ul>
27 </div>
28 )
29}
30
31export default App

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:

App.js
1import { useEffect, useState } from "react"
2
3function App() {
4 const [posts, setPosts] = useState([])
5
6 useEffect(() => {
7 fetch(`https://jsonplaceholder.typicode.com/posts`)
8 .then(response => response.json())
9 .then(data => {
10 setPosts(data)
11 })
12 .catch(e => {
13 console.log(e)
14 })
15 }, [])
16 return (
17 <div className="App">
18 <ul>
19 {posts.map(post => (
20 <li key={post.id}>{post.title}</li>
21 ))}
22 </ul>
23 </div>
24 )
25}
26
27export default App

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

Do follow me on twitter where I post developer insights more often!

© 2024 CodingDeft.Com