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
Document how to batch RTK Query mutations properly #2203
Comments
From the "endpoint specification" side, there is literally no difference between queries and mutations, apart that queries provideTags and mutations invalidateTags. Doing it with a |
Thanks, that helped. I was able to get it working using this:
I still think it would be good to show this in the docs, though. |
PRs to the docs are always welcome :) |
I know. For now I wanted to at least record it as an issue. |
@phryneas just wanted to add that this is not a good solution when using an auto generated RTK api file. |
Agree with @giladv I have to call two mutations on an update of a record. Two different endpoints. Both invalidate the same tag. Frequently results in race conditions and the user only sees part of the update in the UI. And the API file is generated from OpenAPI |
Short answer is that isn't a use case we considered in the initial design, there haven't been many requests for it (other than this thread), and designing that functionality isn't a thing that's on our radar. Not saying it's impossible or will never be done, just that it's not a thing we've spent time thinking about. |
Removing the actual implementation details for a moment, is it not a concern that two mutations called in quick succession - irrespective of what they are doing - would cause a race condition if they try an invalidate the same tag? To me that sounds like a bug that could raise it's head in any number of scenarios outside of the one in this thread. |
@slashwhatever : I don't see it as a "bug" in the sense of "the library code is behaving in an unexpected or unintended way", no. I would potentially see it as a limitation in the design, but the library code is working as intended as far as I know. |
Are more use-cases helpful for you? If so: Currently, I have a list of document ids of unknown length and I need to fetch metadata and preview content for all those documents. But every document needs its own request. And I need this metadata for further calculations, not in separate components where this wouldn't be a problem. E.g.: const documentIds = ['1', '2', '3', '4'] Would result in those requests:
|
Here's an example of how I resolved my use case:
In this specific case, the order of requests was important. If the first failed, it should not send the second and return the error. There wasn't any way around the problem that we generate our code from OpenAPI but we've dealt with that internally. You could, I guess, set up another extended api for your manually created ones and just inject it with @alinnert Not sure if this helps you think about how to solve for your use case, but I figured it was worth sharing in case someone gets some use from it. |
Here's another use case with a workaround. Use case: const { data: items, isFetching: itemsIsFetching, isSuccess: itemsIsSuccess } = useGetItemQuery();
const [ updateItemName ] = usePutItemNameMutation();
const [ updateItemDescription ] = usePutItemDescriptionMutation();
React.useEffect(() => {
// Run only when fetching is complete
if (itemsIsFetching || !itemsIsSuccess) return;
// Perform actions based on the updated item list
// ...
}, [itemsIsFetching]);
const onSave = async () => {
await updateItemName("itemId", "someName");
await updateItemDescription("itemId", "someDescription");
}; The Workaround: const [skip, setSkip] = React.useState(false);
const { data: items, isFetching: itemsIsFetching, isSuccess: itemsIsSuccess } = useGetItemQuery({ skip });
//...
const onSave = async () => {
setSkip(true); // The items list is emptied
await updateItemName("someName");
await updateItemDescription("someDescription");
setSkip(false); // Triggers a reload
}; There are many drawbacks to this workaround, but it works - it disables refetching of the item list while the updates are being applied, and then enables it, which causes the It would be best if we could batch multiple mutations, as proposed by giladv. |
I'm also having this issue. Consider the following example: list: builder.query({
providesTags: () => ["Item"]
}),
update: builder.mutation({
invalidatesTags: () => ["Item"]
})
const [list] = useListQuery()
const [update] = useUpdateMutation()
const onChange = async () => {
const result1 = await update(...) // Update item 1
if ("error" in result1) {
showErrorToast()
} else {
const result2 = await update(...) // Update item 2
}
} After |
@marcus13371337 You could give the CI build of #3116 a try and see if that is what you need. |
A hopeful fix for this is now available in https://github.com/reduxjs/redux-toolkit/releases/tag/v2.0.0-beta.4 ! Please try it out and let us know if it resolves the concerns. |
Haven't heard anything. Will assume this is fixed unless someone says otherwise! |
I feel that the documentation needs to cover the following scenario.
I have an array of objects that I need to send to the API. The API only allows mutating one object per request. What is a good way to do this while:
I understand mutations can probably use a
queryFn
to do this, but the docs only cover how to do multiple fetches.The text was updated successfully, but these errors were encountered: