Lesson 2. Trigger side effects with useEffect 4. Async functions
The function passed to useEffect can only return one thing: another function
called when the component is unmounted. It isn’t possible to return anything
else.
It doesn’t look like a big constraint, but it means that the following code is invalid:
useEffect(async () => {const res = await fetch('http://some.api')const data = await res.json()setData(data)}, [])
If you execute it, React will give you an error, telling you that you returned
something that isn’t a function, a promise in this case. This is because this
code with an async is equivalent to:
useEffect(() => {return fetch('http://some.api').then((res) => res.json()).then((data) => setData(data))}, [])
And unfortunately it is forbidden to return a promise. This is sad, because
async functions are very nice to use. The good news is that some tricks will
make you able to use such functions, and make React happy:
useEffect(() => {// First declare the async functionconst fetchData = async () => {const res = await fetch('http://some.api')const data = await res.json()setData(data)}// Then call it (without `await`)fetchData()})
You can even declare the async function and call it immediately:
useEffect(() => {;(async () => {const res = await fetch('http://some.api')const data = await res.json()setData(data)})()})
Be careful if you need to return a clean-up function. The function passed to
useEffect must return it, not the async function you declare inside. If you
use a flag in this clean-up function, you may have to declare it outside of the
async function:
useEffect(() => {let active = true;(async () => {const res = await fetch('http://some.api')const data = await res.json()if (active) {setData(data)}})()return () => (active = false)})