I’ve been using Redux for few time and i’m struggling with a Thunk answer…
In my slice, I’m calling an async function "handleBoxDeliveryAsync"
extraReducers: (builder) => {
builder
.addCase(handleBoxDeliveryAsync.fulfilled, (state, action) => {
if (state.scanMode === "remove") {
return;
}
const payload = action?.payload?.payload as Data;
const box = payload.data.resource;
//If box hasn't COLLECTED status
if (box.status !== "COLLECTED") {
toast.warn("Le bac de collecte n'est pas disponible à la livraison");
return;
}
//If box hasn't been scanned yet
if (!state.boxes.find((b) => b.external_id === box.external_id)) {
state.boxes.push({ external_id: box.external_id, weight: 0 });
toast.success("Le bac a été ajouté");
return;
}
//If box has already been scanned
toast.warn("Le bac a déjà été scanné");
})
...
this Thunk is responsible to play different functions depending on the "scanMode" (QRCode Reader)
export const handleBoxDeliveryAsync = createAppAsyncThunk(
"collectDelivery/handleBox",
async (code: string, store) => {
try {
if (store.getState().deliveryCollect.scanMode === "add") {
return store.dispatch(getDeliveryBoxAsync(code));
}
if (store.getState().deliveryCollect.scanMode === "remove") {
return store.dispatch(removeDeliveryBoxAsync(code));
}
} catch (e) {
return Promise.reject(e); // Explicitly reject the promise if an error occurs.
}
}
);
export const getDeliveryBoxAsync = createAppAsyncThunk(
"collectDelivery/getBox",
async (code: string) => {
try {
return await getBox(code);
} catch (e) {
return Promise.reject(e);
}
}
);
export const removeDeliveryBoxAsync = createAppAsyncThunk(
"collectDelivery/removeBox",
async (code: string, thunk) => {
if (
thunk
.getState()
.deliveryCollect.boxes.map((b) => b.external_id)
.includes(code)
) {
return Promise.resolve(code);
}
return Promise.reject(code);
}
);
My problem is that when "getDeliveryBoxAsync" is rejected, "handleBoxDeliveryAsync" is still considered as "fulfilled". Any idea why?
Thanks a lot
I tried to handle error and Promises
2
Answers
I found a solution! I moved my logic in to the "getDeliveryBoxAsync"
Issue
The
handleBoxDeliveryAsync
is synchronously returning, e.g. resolving, the result of dispatching either of thegetDeliveryBoxAsync
orremoveDeliveryBoxAsync
actions, which both do their own asynchronous work. By the time either of them encounter any issues and throw/reject, it’s too late,handleBoxDeliveryAsync
resolved with a value that is another Promise.Solution
Seems you would like to wait for the result of either
getDeliveryBoxAsync
orremoveDeliveryBoxAsync
actions to resolve prior to allowinghandleBoxDeliveryAsync
to settle. You also don’t need to explicitly returnPromise.resolve
/Promise.reject
when usingcreateAsyncThunk
actions, Redux-Toolkit handles this for you.For more details see Handling Thunk Results.