How to Call an Async Function Inside a Useeffect() in React

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



Leave a reply



Submit