Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RTKQ: Mutation gets stuck in 'Pending' despite rejection from the server. #1376

Closed
abitbetterthanyesterday opened this issue Aug 3, 2021 · 32 comments

Comments

@abitbetterthanyesterday
Copy link

abitbetterthanyesterday commented Aug 3, 2021

Hi,

On multiple places, since I've updated our package the mutation is stuck on 'Pending' even when an error is thrown.

See screenshot and code below.
The server returns 422, but the mutation doesn't get rejected.

It works with fulfilled mutation, but not rejected ones.
I have the issue in multiple places in my codebase and had to revert back to handling the state manually.

Any clues?
Thank you!

// Mutation
  verifyEmail: builder.mutation({
      query: ({ key, email }) => ({
        url: `membership/validate-email/${key}/${email}`,
        method: "PUT",
      }),
      
 // In my component

   const [
    verifyEmailMutation,
    { isLoading, isError, isSuccess, isUninitialized },
  ] = useVerifyEmailMutation();
  
  <button onClick={() => { isUninitialized && verifyEmailMutation({ key, email }); } > Button </button>

Screen Shot 2021-08-03 at 10 59 28

@phryneas
Copy link
Member

phryneas commented Aug 3, 2021

Could you try to create a reproduction for this?

@rana944
Copy link

rana944 commented Nov 29, 2021

@phryneas ,

Thank you so much for such awesome package. I have used it inside my current app and I am literally enjoying this .

One thing, I have been struggling with is the Pending state of mutation.

I have a scenario where I have been using RTK mutation to fetch data from server on demand. However, when ever I get a 500 error, it gets logged to my middleware

export const rtkQueryErrorLogger: Middleware = (api: MiddlewareAPI) => (next) => (action) => {
   console.log(isRejected(action));
   if (isRejectedWithValue(action)) {
        console.warn('We got a rejected action!')
        console.log({ ...action?.payload, data: '', })
        ShowCustomError(action.payload);
    }
    return next(action);
}

but, the mutation is always in Pending state, not even giving any error state.

As for now, I can see, that I will have to switch to the asyncThunk logic, and managing the state manually.

Can you please provide me some reference to manually trigger the rejection of mutation. So, I can get through it.

Thanks

@phryneas
Copy link
Member

@rana944

Could you try to create a reproduction for this?

this applies here as well. without any code showing this in a reproducable way I have no idea what is going on.

@rana944
Copy link

rana944 commented Nov 29, 2021

@phryneas ,

Thank you so much for such quick response.

I have managed to resolve this issue by using custom base query (Axios Base query).

This is how, I have achieved this,

export const testApi = createApi({
    reducerPath: 'testApi',
    baseQuery: axiosBaseQuery(),
    endpoints: (builder) => ({
        getTopTestItems: builder.mutation<TopTestItem[], TopTestParams>({
            query: (data) => getInterceptor(URLS.TEST1, data, data.token),
        }),
        getTestItems: builder.mutation<TestItem[], TestParams>({
            query: (data) => getInterceptor(URLS.TEST2, data, data.token),
            transformResponse: (response: { data: TestItem[] }) => response.data
        }),
    }),
});

This is the code my GET request interceptor

const getInterceptor = (url: string, params: any, token?: string | undefined) => {
    return {
        url,
        method: 'GET',
        params,
        headers: {
            'Content-Type': 'application/json;charset=UTF-8',
            'Authorization': `JWT ${token}`,
        },
    }
}

This is the code for my custom base query

const axiosInstance = axios.create({
    baseURL: BASE_URL,
});

const axiosBaseQuery = (): BaseQueryFn<any> => async (
    requestOptions,
) => {
    try {

        const result = await axiossInstance({
            ...requestOptions,
        });
    
        return { data: result.data };
    } catch (e: any) {
        return { error: e?.message }
    }
}

This is how I am calling the above mutation,

const [
    getTopTestItems,
    {
        isLoading,
        data,
    }
] = useGetTopTestItemsQuery();

useEffect(() => {
    const testParams = { };
    getTopTestItems({ ...testParams });
}, [])

Thank you

@phryneas
Copy link
Member

@rana944 I need a CodeSandbox, git repository or something else that shows me the problem, not the workaround.
If there is a problem, we need to find and fix it in RTK-Query, so that not everyone has to go for the workarounds you have here.

But without a reproduction I have no idea what to look for.

@polaroidkidd
Copy link

Hi, I'm currently facing the similar issue and have a reproducible repo here: https://github.com/polaroidkidd/librephotos-frontend/tree/feat/migrate-ts--auth-state

I defined the request here and I'm using it on the signup page here.

The successful query goes through as advertised, but when I try to sign up with the same user name twice, the api correctly returns 400 correctly and the rejected response is logged out here, but the status remains pending

To get talking to the api you'd have to clone https://github.com/LibrePhotos/librephotos-docker, rename librephotos.env to .env and run docker-compose up -d.

I'm fairly sure I've misconfigured something here somehwere since RTK-Query is still new to me, but seeing as there's already a ticket for it and you mention needing a reproducible example, I thought I'd throw my hat in the ring.

@polaroidkidd
Copy link

I did some further digging and found a bug in my zod declarations, which stopped the mutation from entering the fulfilled state.

It wasn't related to this after all.

@nofear144
Copy link

Got the same issue when i use GET request with Lazy Query and got 500 error from server, status stacked in "Pending" position...

@phryneas
Copy link
Member

@nofear144 I can only quote myself from this issue:

without a reproduction I have no idea what to look for.

@amandeep-qasource
Copy link

amandeep-qasource commented Oct 5, 2022

Got the same issue when I use POST request and got success status from the server but the status was stuck in the "Pending" position.

@phryneas
Copy link
Member

phryneas commented Oct 5, 2022

Cool.
Could someone at this point maybe even just try to create a reproduction of this instead of saying "I have this problem too"?

Because obviously we have never encountered this. We cannot help you otherwise.

@amandeep-qasource
Copy link

Cool. Could someone at this point maybe even just try to create a reproduction of this instead of saying "I have this problem too"?

Because obviously we have never encountered this. We cannot help you otherwise.

Thank you so much for your quick response!

I am calling a POST API twice in a component using mutation
For first-time mutation call on button click, it is working fine, getting response perfectly fine, but when the same API is called again from button click event it is pausing at the pending status and no output is coming.

@phryneas
Copy link
Member

phryneas commented Oct 5, 2022

I need a reproduction with code that I can run on my machine and see it for myself.

That could be a GitHub repo, a CodeSandbix or a Replay recording.

@v-x2
Copy link

v-x2 commented Oct 8, 2022

Same problem. I know that you're looking for a snippet to reproduce the error. But actually it seems to be random (I tried to create a code sandbox for you but the error disappeared there..)

Till now, I've tried to change the API endpoint name and the tag and the issues seems to disappear for a while, but after some time it appears again. Could be something related to the cache?

@phryneas
Copy link
Member

phryneas commented Oct 8, 2022

@v-x2 I really can't tell. I'd at least need a replay recording of this happening once.

@dominikberse
Copy link

I encountered a similar problem, but it was probably just misusage from my side. For me the request kept hanging as pending because I had a request argument that depended on the current time, which of course changed with every execution.

Something like this:

  const since =
    listState === 'closed'
      ? subDays(new Date(), 90)
      : listState === 'new'
      ? subDays(new Date(), 7)
      : undefined;

  const {
    currentData,
    error,
    isFetching,
  } = useGetDataQuery({
    since: since?.toISOString(),
  });

I resolved this by using the current date without time as a reference point, so since stays constant. Since this was probably just my fault, I did not take the time to set up a repository. However I thought I should just quickly share my finding.

If it is helpful to you, I can set up a repository reproducing this behavior as soon as I have the time.

@phryneas
Copy link
Member

@dominikberse no need for a repo, that's really just misuse and nothing we could debug or fix on our side (as it could be intended just as well). But thanks a lot for sharing, maybe it helps someone here!

@Geemarn
Copy link

Geemarn commented Oct 26, 2022

i encountered similar issues but after removing the middleware am using, it worked as expected.

/** Log a warning and show a notification! **/
const rtkQuerySuccessLogger =
(api: MiddlewareAPI) => (next: any) => (action: { meta: { arg: { type: string } } }) => {
if (isFulfilled(action)) {
if (action.meta.arg.type === 'mutation') {
return message.success('Action Successful!');
}
}
return next(action);
};

@phryneas
Copy link
Member

@Geemarn yes, that middleware will stop the actions from ever reaching the reducer.

/** Log a warning and show a notification! **/
const rtkQuerySuccessLogger =
(api: MiddlewareAPI) => (next: any) => (action: { meta: { arg: { type: string } } }) => {
if (isFulfilled(action)) {
if (action.meta.arg.type === 'mutation') {
+ next(action)
return message.success('Action Successful!');
}
}
return next(action);
};

You always have to call next(action) or the action will never reach the store.

Generally I'd recommend you look at the Listener Middleware for something like that

@Geemarn
Copy link

Geemarn commented Oct 26, 2022

yeah, thanks..just observed it now

@Abolfazl2647
Copy link

I have the same issue and provide a codeSandBox for you guys.

but I'm not sure if you can actually make a request to my server feel free to check out the code.
I must say I actually test this code and in my localhost, I am able to see a status freeze in pending for my getCandles query but getInstrument works as expected.

@phryneas
Copy link
Member

@Abolfazl2647 your code just makes a new request every time the component rerenders.

Every time the component rerenders, new Date().toISOString() will be a different value, so now RTK Query goes ahead and starts another request. That way, you will never finish loading.

@Abolfazl2647
Copy link

@phryneas thank you, I should see that sooner.
sorry to bother you.😖

@axinvd
Copy link

axinvd commented Dec 21, 2022

codeSandBoxExample
Mutation is stuck in pending status if get error in reducer added by addMatcher

@markerikson
Copy link
Collaborator

@axinvd : yeah, that's to be expected. If an error is thrown in the reducer, then the state never actually gets updated.

@vasimshaikhh
Copy link

vasimshaikhh commented May 2, 2023

i am getting the same error in Post Mutation , but the Args i passed is Successfully originated inside originalArgs!! what should i do now

const [respoInfo, response] = useEventUserMutation()
console.log(response,'responssdsdsd')

useEffect(() => {
        (async () => {
            if (event_id !== undefined || null) {
                await  respoInfo(event_id)
            }           
        })()
        console.log(response,'responssdsdsd')
},[event_id])

console.log(response, 'reponse')
useEffect(() => {
    if (response.isSuccess === true) {
        console.log(response,'Done ')
    }
},[response])

//mutation code

eventUser: builder.mutation({
query: (event_id) => ({
url:'eventuser',
method: 'POST',
body: event_id,
headers: {
'Content-Type':'application/json'
}
})
}),

originalArgs : 39 //response args

//working in postMan

@azad-source
Copy link

azad-source commented Jun 10, 2023

Hello! Why this issue is closed and how did you resolve this?
Today is 2023 and I faced the same problem when I used RTK Query.

@phryneas
Copy link
Member

@azad-source as you can read here, they had manual code in a reducer that was erroring. You likely have a different problem. Please open a new issue and provide a reproduction or a replay recording of the problem.

@azad-source
Copy link

@phryneas thanks! I'll try to hide my reducer's slice and I'll check if the problem goes away or not. May be I have the same reason. :)

@pmoradei
Copy link

pmoradei commented Jul 19, 2023

Hello everyone, I ran into this problem because I was doing a mutation call into a popup react component that is unmounted just after the mutation call :

const [doMutation, res] = useSomeMutation();
  /* some code...*/
() => {
 doMutation({...});
 //this method call close the popup so react unmount the component
 onValidate();
}

Adding 'await' before the mutation call helps resolve this because the "res" variable is updated before the component is unmounted:

async () => {
 await doMutation({...});
 //this method call close the popup so react unmount the component
 onValidate();
}

Hope it'll help someone :)

@kouroshey
Copy link

kouroshey commented Jun 23, 2024

I did some further digging and found a bug in my zod declarations, which stopped the mutation from entering the fulfilled state.

It wasn't related to this after all.

Hi. I have same issue with ZOD & RTKQ. Can u explain how to resolve this?

@kouroshey
Copy link

I did some further digging and found a bug in my zod declarations, which stopped the mutation from entering the fulfilled state.
It wasn't related to this after all.

Hi. I have same issue with ZOD & RTKQ. Can u explain how to resolve this?

solved :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests