I have a simple component that makes an async request when some state changes:
const MyComp = () => {
const [state, setState] = useState();
const [result, setResult] = useState();
useEffect(() => {
fetchResult(state).then(setResult);
}, [state]);
return (
<div>{result}</div>
);
};
The problem is, sometimes the state
changes twice in a short lapse of time, and the fetchResult
function can take a very different amount of time to resolve according to the state
value, so sometimes this happens:
As you can guess, as state
now is state2
and not state1
anymore, I would like result
to be result2
, ignoring the response received in the then
of the -obsolete- first effect call.
Is there any clean way to do so?
CodePudding user response:
I've not tested this... but my initial thought would be if you have the state in the response, you could check if the state fetched matches the current state. If not, then the state has changed since the request and you no longer care about the response so don't set it.
useEffect(() => {
fetchResult(state).then((response) => {
response.state === state ? setResult(response.data) : false;
});
}, [state]);
You might also be able to do it by keeping a record of the fetchedState on each request.. and again discard it if it no longer matches.
useEffect(() => {
let fetchedState = state;
fetchResult(fetchedState).then((response) => {
fetchedState === state ? setResult(response) : false;
});
}, [state]);
CodePudding user response:
I would suggest you setup some kind of request cancellation method in the useEffect cleanup function.
For example with axios, it looks like that:
const MyComp = () => {
const [state, setState] = useState();
const [result, setResult] = useState();
useEffect(() => {
const source = axios.CancelToken.source();
fetchResult({state, cancelToken: source.cancelToken }).then(setResult);
return () => {
source.cancel()
}
}, [state]);
return (
<div>{result}</div>
);
};
You have a similar API with fetch called AbortController
What this will do is it will cancel the stale requests if your state changed so only the last one will resolve (and set result).