returning promise from useEffect - reactjs

I was going through the article https://www.robinwieruch.de/react-hooks-fetch-data.
It gives the below 2 snippets to demonstrate how to deal with promises in useEffect. The first one throws an error while to second one doesnt.
first snippet -
useEffect(async () => {
const result = await axios(
'https://hn.algolia.com/api/v1/search?query=redux',
);
setData(result.data);
}, []);
second snippet -
useEffect(() => {
const fetchData = async () => {
const result = await axios(
'https://hn.algolia.com/api/v1/search?query=redux',
);
setData(result.data);
};
fetchData();
}, []);
Why does the second not throw an error, when fetchdata() is called it will return a promise, and thus a promise will be returned from useEffect too. How is the second snippet different from the first one ?

You can only return nothing or a cleanup function for useEffect hook.
The reason the first snippet is throwing an error is because you marked the function async and the functions that are marked async will always return a promise.
//The function is marked async
useEffect(async () => {
const result = await axios(
'https://hn.algolia.com/api/v1/search?query=redux',
);
setData(result.data);
}, []);
It breaks the rule of returning either nothing or a cleanup function.
However In the second snippet, you are using useEffect function to call an async function, but since the useEffect function itself is not async, that means it is not returning a promise
//this is not marked async
useEffect(() => {
const fetchData = async () => {
const result = await axios(
'https://hn.algolia.com/api/v1/search?query=redux',
);
setData(result.data);
};
fetchData();
}, []);

From what l know you cant use promise directly on React Hook. You can use it inside in function and it will work. Hooks are there so that you do not need to use classes in React.
More about Hooks => https://reactjs.org/docs/hooks-overview.html

Related

react-dom.development.js:86 Warning: useEffect must not return anything besides a function, which is used for clean-up

I can't find my error... Can anyone help me please?
const [testArtData, setTestArtData] = useState([]);
useEffect(() => {
const getMyNfts = async () => {
const openseaData = await axios.get(`https://testnets-api.opensea.io/assets?asset_contract_address=0x4Bef569089846759595C1ed598a3bD6D249FD7c4&order_direction=asc`);
console.log(openseaData.data.assets);
setTestArtData(openseaData.data.assets);
}
return getMyNfts()
}, [])
Everytime I get this error:
Error
You would help me so much! Thanks
The solution for this is to make a async function inside the useEffect itself and then call it underneath it:
useEffect(() => {
// wrap your async call here
const loadData = async () => {
setUsersLoading(true);
const result = await getUsers();
setUsers(result);
setUsersLoading(false);
};
// then call it here
loadData();
}, []);
However, React does not recommend it because everything in useEffect is to be executed in a seprate thread and thus returned value may be needed by some other part of code and there is a chance of un-predictable behavior.

Why is my React useEffect not loading again when I refresh the page?

I am using a useEffect to get information from firebase and set my redux state thereafter. When I open the page for the first time, all my components contain the correct information. As soon as I refresh the page, all the information is set to nothing? I think it is because the useEffect does not execute again for some reason. Here is my code below:
useEffect(async () => {
setLoading(true);
const fetchData = async () => {
await getConfigs().then((response) => {
const obj = response;
setRedux(obj[0]);
});
};
fetchData();
}, []);
I think the problem is that you provide an async function as a callback to useEffect, which is not allowed. Just get rid of it, like so:
useEffect(() => {
setLoading(true);
const fetchData = async () => {
// Also, you either await or use .then(), not both
const response = await getConfigs();
const obj = response;
setRedux(obj[0]);
};
fetchData();
}, []);

React axios .then() doesn't run

useEffect( () => {
const fetchdata = async () => {
return ( await axios.get(serverPath).then(res=>{
addNewSubtitle(res.data)
}))
};
const result = fetchdata(); //addnewSubtitle(result.data)}, [serverPath])
The .then doesn't run and I have also tried the result.data commented below which returns undefined.
I have checked the syntax again and again and it seems correct. I don't know what could cause the then function to not run
You need to return what’s in your .then() to use it—
return ( await axios.get(serverPath).then(res=>{
return addNewSubtitle(res.data)
}))
useEffect(() => {
async function request() {
const fetchdata = async () => await axios.get(serverPath).then(res => res.data)
const result = await fetchdata()
}
request()
}, [serverPath])
I was able to solve it like this:
useEffect(() => {
function request() {
const fetchdata = async () => await axios.get( serverPath )
const result = fetchdata()
result.then(res=>addNewSubtitle(res.data))
}
request()
}, [serverPath])
The result was a promise object and when .then was called outside the fetchdata function it worked
useEffect(()=>{
async function fetchData(){
await axios.get(serverPath).then(res=>addNewSubtitle(res.data))
}
fetchData()
}, [serverPath])
i don't know what you're doing but this is my basic format on axios call within the useEffect hook

Unexpected behavior when fetching data with hooks

I'm trying to fetch data with hooks, and I'm getting an unexpected result.
When I try to use an async callback with useEffect, it throws a warning saying it's bad practice, even though the code works (Commented out in the attached example below)
But when I try to declare an async function within useEffect, it doesn't work (example below)
What am I missing?
https://codesandbox.io/s/mystifying-aryabhata-glqwz?fontsize=14
You should put all the effect logic inside the fetchData() and the call it separately within the useEffect:
useEffect(() => {
const fetchData = async () => {
try {
const result = await axios("https://hn.algolia.com/api/v1/search?query=redux");
setData(result.data);
} catch (e) {
console.log(e);
}
}
fetchData();
}, []);
You can fix it like this :
useEffect(() => {
const fetchData = async () => {
try {
const result = await axios(
'https://hn.algolia.com/api/v1/search?query=redux',
);
setData(result.data);
} catch(e) {
console.log(e);
}
}
fetchData();
}, []);
https://codesandbox.io/s/cocky-water-c0w9i
The problem in your code was, in these lines :
const result = fetchData();
setData(result.data);
here fetchData is async and will return a promise not the actual result, and so result.data is undefined
the callback passed to useEffect must return either a cleanup callback or undefined, when you mark a function as async, it returns a promise implicitly
you can create a function inside the useEffect callback that you can mark as async
React.useEffect(() => {
async function fetchData() {
// write your request
}
fetchData();
})
look to this solution in the
simple solution

Preferred way of using asynchronous function in useEffect

I know two ways to use asynchronous functions in useEffect. I read somewhere that the first way is wrong. Which way do you think is better?
first method
async function fetchData() {
const result = await axios(
'https://hn.algolia.com/api/v1/search?query=react',
);
setData(result.data);
}
useEffect(() => {
fetchData();
}, [miliko]);
second method
useEffect(() => {
async function fetchData() {
const result = await axios(
'https://hn.algolia.com/api/v1/search?query=react',
);
setData(result.data);
}
fetchData();
}, [miliko]);
Both solutions are correct and will work as long as the data that fetchData uses is within its lexical scope
The only difference in the two approaches is that a new reference for fetchData will be created on every render in the first case, whereas in the second case a new reference will be create only on initial render and when miliko changes
To keep the relevant code together, you can go ahead with the second approach which will it easier for you to cancel the previous request if a new request is made so that you don't see inconsistencies
useEffect(() => {
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
async function fetchData() {
const result = await axios(
'https://hn.algolia.com/api/v1/search?query=react', {
cancelToken: source.token
}
);
setData(result.data);
}
fetchData();
return () => {
source.cancel('Effect cleared');
}
}, [miliko]);

Resources