How to call an async function inside a UseEffect() in React?
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();
}, []);
React Hook Warnings for async function in useEffect: useEffect function must return a cleanup function or nothing
I suggest to look at Dan Abramov (one of the React core maintainers) answer here:
I think you're making it more complicated than it needs to be.
function Example() {
const [data, dataSet] = useState<any>(null)
useEffect(() => {
async function fetchMyAPI() {
let response = await fetch('api/data')
response = await response.json()
dataSet(response)
}
fetchMyAPI()
}, [])
return <div>{JSON.stringify(data)}</div>
}
Longer term we'll discourage this pattern because it encourages race conditions. Such as — anything could happen between your call starts and ends, and you could have gotten new props. Instead, we'll recommend Suspense for data fetching which will look more like
const response = MyAPIResource.read();
and no effects. But in the meantime you can move the async stuff to a separate function and call it.
You can read more about experimental suspense here.
If you want to use functions outside with eslint.
function OutsideUsageExample({ userId }) {
const [data, dataSet] = useState<any>(null)
const fetchMyAPI = useCallback(async () => {
let response = await fetch('api/data/' + userId)
response = await response.json()
dataSet(response)
}, [userId]) // if userId changes, useEffect will run again
useEffect(() => {
fetchMyAPI()
}, [fetchMyAPI])
return (
<div>
<div>data: {JSON.stringify(data)}</div>
<div>
<button onClick={fetchMyAPI}>manual fetch</button>
</div>
</div>
)
}
If you use useCallback, look at example of how it works useCallback. Sandbox.
import React, { useState, useEffect, useCallback } from "react";
export default function App() {
const [counter, setCounter] = useState(1);
// if counter is changed, than fn will be updated with new counter value
const fn = useCallback(() => {
setCounter(counter + 1);
}, [counter]);
// if counter is changed, than fn will not be updated and counter will be always 1 inside fn
/*const fnBad = useCallback(() => {
setCounter(counter + 1);
}, []);*/
// if fn or counter is changed, than useEffect will rerun
useEffect(() => {
if (!(counter % 2)) return; // this will stop the loop if counter is not even
fn();
}, [fn, counter]);
// this will be infinite loop because fn is always changing with new counter value
/*useEffect(() => {
fn();
}, [fn]);*/
return (
<div>
<div>Counter is {counter}</div>
<button onClick={fn}>add +1 count</button>
</div>
);
}
how yo use an async method inside useEffect() hook
Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
You are breaking the rules of hooks. Hooks are only valid when called while synchronously rendering a React component. An effect runs separately after a componenent renders. So you cannot call a hook from an effect.
And yes you are calling a hook from an effect because this effect:
useEffect(() => {
await fetchMyApi(values.code)
}, [values]);
Calls the fetchMyApi
function, which calls a hook:
await useQuery('data', () => /* ... */)
You are using react query incorrectly.
First make your fetchMyApi
just do it's async task, and nothing else:
export const fetchMyApi = (code) => {
return clientAPIs.getData(code)
};
Then call useQuery
from the root of your functional component:
function MyComponent() {
const { data } = useQuery('data', () => fetchMyApi('some code here'))
}
The documentation should take you the rest of the way from here
Proper use of useEffect with useState called within async function
This is common pattern in react
const Component = () => {
const [data, setData] = useState();
useEffect(()=>{
const fetchData = async () => {
const data = await fetch();
setData(data);
}
fetchData();
}, [])
return <div>{JSON.stringify(data)}</div>
}
Async function not working inside UseEffect Hook
useEffect(() => {
console.log("Inside UseEffect"); //logs the output
(async () => {
var url = `https://xx.yy.zz/?param={"request_type":"query_osm_circle","lat":${region.latitude},"lng":${region.longitude},"radius":3,"limit":10}`;
try {
let response = await fetch(
url,
);
let responseJson = await response.json();
console.log(responseJson); //does not log the output
setTargets(responseJson);
} catch (error) {
console.error(error);
}
})()
},[]);
Proper async await syntax for fetching data using useEffect hook in React?
You should not make your useEffect
function async
, but you can create an async
function inside useEffect
useEffect(() => {
const getDatas = async () => {
const response = await fetch("https://jsonplaceholder.typicode.com/posts");
const data = await response.json();
setApiData(data);
}
getDatas()
});
or even
useEffect(() => {
(async () => {
const response = await fetch("https://jsonplaceholder.typicode.com/posts");
const data = await response.json();
setApiData(data);
)()
});
Putting Async functions into useEffect() hook in React
When setUser
is called, the user
variable still holds old user
information (null
in this case), regardless of async/await
:
await checkUser(); // setUser(something) will not happen until next run
await getGoogleApiKey(); // user is still null
await setAuthListener();
One other choice would be to add another effect when user
changes:
useEffect(() => {
if (user) {
getGoogleApiKey();
}
}, [user]);
Or, call getGoogleApiKey
with the parameter:
const user = await checkUser(); // return user
await getGoogleApiKey(user);
await setAuthListener();
Since the logic gets complex, I would suggest trying the useReducer hook because dispatch simplifies this complex back and forth scenarios.
Related Topics
How to Save a Leaflet Map with Drawn Shapes/Points on It in Shiny
Angular 4.3.3 Httpclient:How Get Value from the Header of a Response
Es6 Template Literals VS. Concatenated Strings
Rails Include JavaScripts Assets Folder Recursively
How Is a JavaScript String Not an Object
Why Is It Frowned Upon to Modify JavaScript Object's Prototypes
Finding Variable Type in JavaScript
How to Return a Variable from Google Maps JavaScript Geocoder Callback
$.Deferred: How to Detect When Every Promise Has Been Executed
How to Execute Array of Promises in Sequential Order
How to Use Source: Function()... and Ajax in Jquery UI Autocomplete
The $.Param( ) Inverse Function in JavaScript/Jquery
"Document.Getelementbyclass Is Not a Function"
Encrypting Data with Ruby Decrypting with Node