Reputation: 2543
I would like to fetch data when the user changes.
To do this I have a useEffect
that triggers when the user
changes, which calls a function to get the data.
The problem is that the useEffect
is called too often because it has a dependency on getData
and getData
changes because it both uses and sets loading
.
Are there ways around this, while still retaining getData
as a function, as I call it elsewhere.
const getData = useCallback(async () => {
if (!loading) {
try {
setLoading(true);
const { error, data } = await getDataHook();
if (error) {
throw new Error("blah!");
}
} catch (error) {
const message = getErrorMessage(error);
setErrorMessage(message);
setLoading(false);
}
}
}, [loading]);
...
useEffect(() => {
const callGetData = async () => {
await getData();
};
callGetData();
}, [user, getData]);
Upvotes: 1
Views: 500
Reputation: 191966
The loading
flag is something that the call sets, and shouldn't be effected by it, so remove it from the useEffect()
, and getData()
functions.
const getData = useCallback(async () => {
try {
setLoading(true);
const { error, data } = await getDataHook();
if (error) {
throw new Error("blah!");
}
} catch (error) {
const message = getErrorMessage(error);
setErrorMessage(message);
} finally {
setLoading(false); // not related, but this would remove loading after an error as well
}
}, []);
useEffect(() => {
const callGetData = async () => {
await getData(user);
};
callGetData();
}, [user, getData]);
Upvotes: 0
Reputation: 266
Try moving loading
from useCallback
to useEffect
. Something like this:
const getData = useCallback(async () => {
try {
const { error, data } = await getDataHook();
if (error) {
throw new Error("blah!");
}
} catch (error) {
const message = getErrorMessage(error);
setErrorMessage(message);
}
}, []);
...
useEffect(() => {
const callGetData = async () => {
await getData();
};
if (!loading) {
setLoading(true);
callGetData();
setLoading(false);
}
}, [user, getData, loading]);
Upvotes: 1