Skip to content

Instantly share code, notes, and snippets.

@artalar
Created March 14, 2023 13:41
Show Gist options
  • Save artalar/9f55237aa9cbc14e8d6ea73f3e534c93 to your computer and use it in GitHub Desktop.
Save artalar/9f55237aa9cbc14e8d6ea73f3e534c93 to your computer and use it in GitHub Desktop.
Dependent effects cancelation with Reatom
// new API: reatomAsync automatically cancels the previous request
// and all dependent requests when the new request is triggered
const getList = reatomAsync.from(getListApi).pipe(withDataAtom([]));
const getId = reatomAsync.from(getIdApi).pipe(withAbort());
onUpdate(getId.onFulfilled, (ctx, { data: id }) => getList(ctx, id));
const Component = () => {
const [list] = useAtom(getList.dataAtom);
const handleChange = useAction((ctx, e) => getId(ctx, e.currentTarget.value));
return (
<>
<input onChange={handleChange} />
{list.map(() => "...")}
</>
);
};
// main flow:
// onChange+getId -> +200ms -> getList -> +200ms -> setList
// situation 1: user types slow
// :0ms onChange+getId_1 -> :200ms -> getList_1 -> :400ms -> setList_1
// :500ms onChange+getId_2 -> :700ms -> getList_2 -> :900ms -> setList_2
// setList was called twice and it is correct,
// because from :400ms to :500ms we allow to show data from getId_1.
// situation 2: user types fast
// :0ms onChange+getId_1 -> :100ms CANCELED
// :100ms onChange+getId_2+abort(getId_1) -> :300ms -> getList_2 -> :500ms -> setList_2
// setList was called once and it is correct.
// situation 3: user has middle ability to type =D
// :0ms onChange+getId_1 -> :200ms -> getList_1 -> :300ms CANCELED
// :300ms onChange+getId_2 -> :500ms -> getList_2 -> :700ms -> setList_2
// setList was called once and it is correct,
// getId automatically cancels the previous request and all dependent requests.
// current API: useLazyRequest automatically cancels the previous request
// when the new request is triggered
const Component = () => {
const [list, setList] = useState([]);
const [getList] = useLazyRequest({ apiMethod: getListApi });
const [getId] = useLazyRequest({
apiMethod: getIdApi,
async onSuccess({ data: id }) {
const { data } = await getList(id);
setList(data);
},
});
return (
<>
<input onChange={(e) => getId(e.currentTarget.value)} />
{list.map(() => "...")}
</>
);
};
// main flow:
// onChange+getId -> +200ms -> getList -> +200ms -> setList
// situation 1: user types slow
// :0ms onChange+getId_1 -> :200ms -> getList_1 -> :400ms -> setList_1
// :500ms onChange+getId_2 -> :700ms -> getList_2 -> :900ms -> setList_2
// setList was called twice and it is correct,
// because from :400ms to :500ms we allow to show data from getId_1.
// situation 2: user types fast
// :0ms onChange+getId_1 -> :100ms CANCELED
// :100ms onChange+getId_2+abort(getId_1) -> :300ms -> getList_2 -> :500ms -> setList_2
// setList was called once and it is correct.
// situation 3: user has middle ability to type =D
// :0ms onChange+getId_1 -> :200ms -> getList_1 -> :400ms -> setList_1
// :300ms onChange+getId_2 -> :500ms -> getList_2 -> :700ms -> setList_2
// setList was called twice and it is NOT correct,
// because getId does not cancel getList and we show data from getList_1.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment