Search code examples
reactjsnext.jsreduxredux-toolkitredux-thunk

Redux Thunk remains "fulfilled" even when I return a Promise.reject


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


Solution

  • I found a solution! I moved my logic in to the "getDeliveryBoxAsync"

    .addCase(getDeliveryBoxAsync.fulfilled, (state, { payload }) => {
            const box = payload.data.resource;
            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é");
          })
          .addCase(getDeliveryBoxAsync.rejected, (_, { error }) => {
            if (error.code === "ERR_BAD_REQUEST") {
              toast.warn("Le bac n'existe pas");
              return;
            }
            toast.warn("une erreur est survenue");
          })