reduxjs / redux-toolkit

The official, opinionated, batteries-included toolset for efficient Redux development
https://redux-toolkit.js.org
MIT License
10.65k stars 1.16k forks source link

queryFn doesn't update on error, and continues on pending state #4620

Open jesusaguiardev opened 5 days ago

jesusaguiardev commented 5 days ago

Hello!, i'm implementing an api with a single mutation using queryFn

From the docs I understand that, the queryFn is expected to return an object with the following pattern { error: {...} }, but for some reason, when i return an error, the mutation doesn't finish and continues on pending state

this is the code (i'll remove the non-essentials)

import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import dynamicURL from "../dynamicURL";

const baseQuery = fetchBaseQuery({
  baseUrl: API_BASEURL,
});

const paperlessApi = createApi({
  reducerPath: "paperlessApi",
  baseQuery: baseQuery,
  endpoints: (builder) => ({
    validateDatablob: builder.mutation({
      providesTags: ["Paperless"],
      queryFn: async ({ data, env }, api, extraOptions) => {
        const { icgid, dataToDecode, setMetada, setError } = data;

        const decodedData = changeAlgorithm(dataToDecode, setMetada, setError);
        if (!decodedData) {
          return {
            error: { status: 400, message: "Failed to decode the data blob" },
          };
        }

        const dataToValidate = {
          icgid,
          data: { ...decodedData },
        };

        try {
          const setup = {
            method: "POST",
            body: dataToValidate,
            env,
            endpoint: `/courier/document/validate`,
          };
          const requestConfig = dynamicURL(setup);

          const validationResponse = await baseQuery(
            requestConfig,
            api,
            extraOptions
          );

          if (validationResponse?.error) {
            return {
              error: { status: 500, ...validationResponse.error },
            };
          }

          return { data: decodedData };
        } catch (error) {
          return {
            error: {
              status: 500,
              message:
                error.message || "An unknown error occurred during validation",
            },
          };
        }
      },
    }),
  }),
});

export const { useValidateDatablobMutation } = paperlessApi;

export default paperlessApi;

and for clarification, the success path works as expected, if i return { data: whatever } the mutation finalize as expected

this is how im using the mutation

  const [
    validateDataBlob,
    {
      isLoading: isValidatingDatablob,
      isSuccess: dataBlobIsValid,
      isError: dataBlobHasBeenTampered,
    },
  ] = useValidateDatablobMutation();

and calling validateDataBlob inside a useEffect that has other logic, the versions i have are:

 "@reduxjs/toolkit": "1.9.5",
"react-redux": "^8.0.4",
EskiMojo14 commented 5 days ago

yes it does :)

would happily help you if provided any actual details

jesusaguiardev commented 5 days ago

LOL idk how u got the issue bc i didn't click on Submit new issue @EskiMojo14 , i was going to change the title obviously with the proper error im having haha

EskiMojo14 commented 5 days ago

haha, odd - feel free to edit it and I'll reopen

jesusaguiardev commented 5 days ago

i updated the issue @EskiMojo14 thank you for taking my mistake with a lil of humor hahahaha

EskiMojo14 commented 5 days ago

hmm, i don't see anything obvious - have you added some console logs to work out which return { error } line is happening?

jesusaguiardev commented 5 days ago

Yea, i even tried to return the error even before executing the query, like :(

queryFn: async ({ data, env }, api, extraOptions) => {  return {error { ... } } }
jesusaguiardev commented 5 days ago

One finding, on the useEffect i execute the validateDatablob, i have this logic

 const result = await validateDataBlob({
        data: {
          icgid: "",
          dataToDecode: data,
          setMetada,
          setError,
        },
        env: iframeEnv.env?.toUpperCase() || "DEV",
      });
      if (result?.data) {
        setPurchasedProduct(result.data?.type);
        setDecodedBlob(result?.data);
      } else {
        setIsDataBlobValid(false);
      }
    };

If i console log the result when i return an error, it has the error, but idk why the other out of the box states from RTK are not updating

EskiMojo14 commented 5 days ago

do you have any other reducers that are listening for the rejected action (validateDataBlob.matchRejected) that might be throwing errors?