The ‘React Hook Warnings for async function in useEffect: useEffect function must return a cleanup function or nothing’ error is something that we may see when we’re writing React apps.
In this article, we’ll take a look at how to fix the ‘React Hook Warnings for async function in useEffect: useEffect function must return a cleanup function or nothing’ error.
Cause of the Error
This error may occur when we try to pass in an async function as an argument of the first argument of the useEffect
hook.
The useEffect
hook’s first argument cannot be an async function.
If we want to use an async function, then we should define it outside the function and call it.
Or we can define it inside the function and call it.
For instance, instead of writing:
import { useEffect, useState } from "react";
export default function App() {
const [data, setData] = useState({});
useEffect(async () => {
const res = await fetch("https://yesno.wtf/api");
const data = await res.json();
setData(data);
}, []);
return (
<div className="App">
<p>{JSON.stringify(data)}</p>
</div>
);
}
We write:
import { useEffect, useState } from "react";
export default function App() {
const [data, setData] = useState({});
const getData = async () => {
const res = await fetch("https://yesno.wtf/api");
const data = await res.json();
setData(data);
};
useEffect(() => {
getData();
}, []);
return (
<div className="App">
<p>{JSON.stringify(data)}</p>
</div>
);
}
Or we can write:
import { useEffect, useState } from "react";
export default function App() {
const [data, setData] = useState({});
useEffect(() => {
const getData = async () => {
const res = await fetch("https://yesno.wtf/api");
const data = await res.json();
setData(data);
};
getData();
}, []);
return (
<div className="App">
<p>{JSON.stringify(data)}</p>
</div>
);
}
We can’t pass an async function into the useEffect
as its first argument because it may lead to race conditions.
Async functions complete in an indeterminate amount of time.
And hooks order matter.
Therefore, we can’t use async functions in the useEffect
hooka as its argument.
But this doesn’t prevent us from using them.
We can still call then
and catch
in the useEffect
callback.
So we can write:
import { useEffect, useState } from "react";
export default function App() {
const [data, setData] = useState({});
useEffect(() => {
fetch("https://yesno.wtf/api")
.then((res) => res.json())
.then((data) => setData(data));
}, []);
return (
<div className="App">
<p>{JSON.stringify(data)}</p>
</div>
);
}
We can have promises in our code, we just can’t write them as async functions if we want to use the function as an argument of useEffect
.
Conclusion
To solve the ‘React Hook Warnings for async function in useEffect: useEffect function must return a cleanup function or nothing’ error, we shouldn’t pass async function as the first argument of useEffect
.
Instead, we can call promises with functions in different ways.