I would like to call an async function and get the result for my UseEffect.
The fetch api examples i found on the internet are directly made in the useEffect function. If my URL changes, i must patch all my fetchs.
When i tried, i got an error message.
This is my code.
async function getData(userId) {
const data = await axios.get(`http://url/api/data/${userId}`)
.then(promise => {
return promise.data;
})
.catch(e => {
console.error(e);
})
return data;
}
function blabla() {
const [data, setData] = useState(null);
useEffect(async () => {
setData(getData(1))
}, []);
return (
<div>
this is the {data["name"]}
</div>
);
}
index.js:1375 Warning: An effect function must not return anything besides a function, which is used for clean-up. It looks like you wrote useEffect(async () => ...) or returned a Promise. Instead, write the async function inside your effect and call it immediately:
useEffect(() => {
async function fetchData() {
// You can await here
const response = await MyAPI.getData(someId);
// ...
}
fetchData();
}, [someId]); // Or [] if effect doesn't need props or state
Either way, we're now safe to use async functions inside useEffect hooks. Now if/when you want to return a cleanup function, it will get called and we also keep useEffect nice and clean and free from race conditions. Enjoy using async functions with React's useEffect from here on out!
Anti-Pattern: async function directly in the useEffect React can run this async function but can not run the cleanup function. Don't use raw async function directly in the useEffect. useEffect(async () => { console. log('Hi :)') return () => { console.info('Bye!
You cannot directly make the callback function supplied to the useEffect hook async because: async functions implicitly return a promise, and; useEffect expects its callback to either return nothing or a clean-up function.
Here is an example of how you would call a function to fetch data only once - when the component mounts. Copied! import {useEffect, useState} from 'react'; const App = () => { const [data, setData] = useState({data: []}); const [err, setErr] = useState(''); useEffect(() => { // 👇️ this only runs once console.
Create an async function inside your effect that wait the getData(1)
result then call setData()
:
useEffect(() => { const fetchData = async () => { const data = await getData(1); setData(data); } fetchData(); }, []);
If you're invoking it right-away you might want to use it as an anonymous function:
useEffect(() => { (async () => { const data = await getData(1); setData(data); })(); }, []);
It would be best if you did what the warning suggests - call the async function inside the effect.
function blabla() {
const [data, setData] = useState(null);
useEffect(() => {
axios.get(`http://url/api/data/1`)
.then(result => {
setData(result.data);
})
.catch(console.error)
}, []);
return (
<div>
this is the {data["name"]}
</div>
);
}
If you want to keep the api function outside of the component, you can also do this:
async function getData(userId) {
const data = await axios.get(`http://url/api/data/${userId}`)
.then(promise => {
return promise.data;
})
.catch(e => {
console.error(e);
})
return data;
}
function blabla() {
const [data, setData] = useState(null);
useEffect(() => {
(async () => {
const newData = await getData(1);
setData(newData);
})();
}, []);
return (
<div>
this is the {data["name"]}
</div>
);
}
Since getData
returns a Promise you could just use .then
useEffect(() => {
getData(1).then(setData);
}, []);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With