Skip to content

docs: selectInvalidedBy for multiple cache updates across queries#5226

Open
bigcupcoffee wants to merge 10 commits into
reduxjs:masterfrom
bigcupcoffee:patch-1
Open

docs: selectInvalidedBy for multiple cache updates across queries#5226
bigcupcoffee wants to merge 10 commits into
reduxjs:masterfrom
bigcupcoffee:patch-1

Conversation

@bigcupcoffee

Copy link
Copy Markdown

This is a rough sample of what we use in our mobile app to update an entity across 10+ queries without invalidating them all

Switch cases are easier to extend IMO, while in our code we have some abstration layer for draft updaters and entity predicates (as we have secondary identifier plus nested entities), this is more for the devs to figure out if they feel like they need it

For some queries we even have updates outside of redux with an according custom undo return, so this also keeps the room for obscure custom cases (which I wish I didn't have to see & code)

Code definitely feels somewhat weird but I feel like we still need a mention of this usecase for selectInvalidatedBy, for simplicity sake the code could only cover updating the list queries, but I figured I'd present a more complex case at this point, what do you think?

Could probably use some touch up on the wording, feel free to comment 🙏

@codesandbox

codesandbox Bot commented Feb 17, 2026

Copy link
Copy Markdown

Review or Edit in CodeSandbox

Open the branch in Web EditorVS CodeInsiders

Open Preview

@codesandbox-ci

codesandbox-ci Bot commented Feb 17, 2026

Copy link
Copy Markdown

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 11481f5:

Sandbox Source
@examples-query-react/basic Configuration
@examples-query-react/advanced Configuration
@examples-action-listener/counter Configuration
rtk-esm-cra Configuration

@netlify

netlify Bot commented Feb 18, 2026

Copy link
Copy Markdown

Deploy Preview for redux-starter-kit-docs ready!

Name Link
🔨 Latest commit 11481f5
🔍 Latest deploy log https://app.netlify.com/projects/redux-starter-kit-docs/deploys/69e8521e70872800089f4e15
😎 Deploy Preview https://deploy-preview-5226--redux-starter-kit-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@aryaemami59 aryaemami59 added the Documentation Improvements or additions to documentation label Feb 18, 2026
@bigcupcoffee

Copy link
Copy Markdown
Author

@markerikson thoughts?

@aryaemami59 aryaemami59 changed the title docs: selectInvalidedBy for multiple cache updates across queries docs: selectInvalidedBy for multiple cache updates across queries Mar 18, 2026
@aryaemami59 aryaemami59 added the Needs Feedback More input is needed before moving forward. label Mar 18, 2026
@aryaemami59 aryaemami59 requested a review from markerikson March 18, 2026 10:48
@aryaemami59 aryaemami59 added the RTK-Query Issues related to Redux-Toolkit-Query label Mar 18, 2026

@themavik themavik left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The selectInvalidatedBy walk plus per-endpoint updateQueryData is a solid pattern for fan-out cache patches. nit: the sample getNextPageParam stops when lastPage.length < 20 while initialPageParam is 1—readers copy-pasting might get pagination wrong unless the prose calls that out.

@bigcupcoffee bigcupcoffee marked this pull request as ready for review April 12, 2026 22:12

The entity you want to update might be present in multiple differently shaped queries, such as
(infinite) lists, or even inside another entity. If you don't want to invalidate those instead,
you can avoid manually looping through every single cache entry by using [selectInvalidatedBy](https://redux-toolkit.js.org/rtk-query/api/created-api/api-slice-utils#selectinvalidatedby):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
you can avoid manually looping through every single cache entry by using [selectInvalidatedBy](https://redux-toolkit.js.org/rtk-query/api/created-api/api-slice-utils#selectinvalidatedby):
you can avoid manually looping through every single cache entry by using [`selectInvalidatedBy`](https://redux-toolkit.js.org/rtk-query/api/created-api/api-slice-utils#selectinvalidatedby):

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds documentation showing how to perform an optimistic cache update for a single entity that may appear across multiple RTK Query cache entries (detail query + infinite list), using api.util.selectInvalidatedBy to find affected entries.

Changes:

  • Introduces a new “Updates Across Queries” section under Manual Cache Updates.
  • Adds a TypeScript example demonstrating selectInvalidatedBy + updateQueryData for both single-item and infinite-list query shapes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +286 to +316
const patches = entries.map(entry => {
switch (entry.endpointName) {
case 'getPost':
return dispatch(
api.util.updateQueryData(
entry.endpointName,
entry.originalArgs,
(draft) => {
Object.assign(draft, patch)
},
),
)
case 'getPosts':
return dispatch(
api.util.updateQueryData(
entry.endpointName,
entry.originalArgs,
(draft) => {
draft.pages.forEach(page => {
page.forEach(entity => {
if (entity.id === id) Object.assign(entity, patch)
})
})
},
),
)
default:
throw new Error(`Unknown endpoint (${entry.endpointName}) in updatePost's optimistic update`)
}
})

Copilot AI Apr 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Throwing an error here will crash the app during onQueryStarted if any other query provides the same tag but isn’t explicitly handled. For a docs example, it’s safer to ignore/skip unknown endpoints (or handle them with a no-op/log) so adding a new tagged query doesn’t introduce a runtime failure.

Suggested change
const patches = entries.map(entry => {
switch (entry.endpointName) {
case 'getPost':
return dispatch(
api.util.updateQueryData(
entry.endpointName,
entry.originalArgs,
(draft) => {
Object.assign(draft, patch)
},
),
)
case 'getPosts':
return dispatch(
api.util.updateQueryData(
entry.endpointName,
entry.originalArgs,
(draft) => {
draft.pages.forEach(page => {
page.forEach(entity => {
if (entity.id === id) Object.assign(entity, patch)
})
})
},
),
)
default:
throw new Error(`Unknown endpoint (${entry.endpointName}) in updatePost's optimistic update`)
}
})
const patches = entries.reduce((patches, entry) => {
switch (entry.endpointName) {
case 'getPost':
patches.push(
dispatch(
api.util.updateQueryData(
entry.endpointName,
entry.originalArgs,
(draft) => {
Object.assign(draft, patch)
},
),
),
)
break
case 'getPosts':
patches.push(
dispatch(
api.util.updateQueryData(
entry.endpointName,
entry.originalArgs,
(draft) => {
draft.pages.forEach(page => {
page.forEach(entity => {
if (entity.id === id) Object.assign(entity, patch)
})
})
},
),
),
)
break
default:
break
}
return patches
}, [])

Copilot uses AI. Check for mistakes.
}
})

queryFulfilled.catch(() => patches.forEach(patch => patch.undo()))

Copilot AI Apr 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the rollback handler, the callback parameter name patch shadows the outer patch object from the mutation args. Renaming the inner variable (eg patchResult/patchAction) would make the example easier to follow.

Suggested change
queryFulfilled.catch(() => patches.forEach(patch => patch.undo()))
queryFulfilled.catch(() => patches.forEach((patchResult) => patchResult.undo()))

Copilot uses AI. Check for mistakes.

The entity you want to update might be present in multiple differently shaped queries, such as
(infinite) lists, or even inside another entity. If you don't want to invalidate those instead,
you can avoid manually looping through every single cache entry by using [selectInvalidatedBy](https://redux-toolkit.js.org/rtk-query/api/created-api/api-slice-utils#selectinvalidatedby):

Copilot AI Apr 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This link uses an absolute URL, while the rest of this page uses relative links to the local MDX docs (eg ../api/created-api/api-slice-utils.mdx#updatequerydata). Consider switching to a relative link to api-slice-utils.mdx#selectinvalidatedby so the docs work consistently in local/offline builds and across site base URLs.

Suggested change
you can avoid manually looping through every single cache entry by using [selectInvalidatedBy](https://redux-toolkit.js.org/rtk-query/api/created-api/api-slice-utils#selectinvalidatedby):
you can avoid manually looping through every single cache entry by using [selectInvalidatedBy](../api/created-api/api-slice-utils.mdx#selectinvalidatedby):

Copilot uses AI. Check for mistakes.
### Updates Across Queries

The entity you want to update might be present in multiple differently shaped queries, such as
(infinite) lists, or even inside another entity. If you don't want to invalidate those instead,

Copilot AI Apr 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wording is a bit unclear here: “invalidate those instead” reads like it refers to entities rather than queries. Consider rephrasing to “invalidate those queries instead” or “invalidate them instead” for clarity.

Suggested change
(infinite) lists, or even inside another entity. If you don't want to invalidate those instead,
(infinite) lists, or even inside another entity. If you don't want to invalidate those queries instead,

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Documentation Improvements or additions to documentation Needs Feedback More input is needed before moving forward. RTK-Query Issues related to Redux-Toolkit-Query

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants