-
Notifications
You must be signed in to change notification settings - Fork 839
Forms: Fix last page remove items from view bug #45740
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
base: trunk
Are you sure you want to change the base?
Conversation
Introduces a helper function, invalidateCacheAndNavigate, to centralize cache invalidation and page navigation logic after bulk actions (spam, not spam, restore, trash, delete) in the inbox dataviews. This ensures accurate counts and correct pagination after items are removed from inbox, spam, or trash, improving consistency and maintainability.
|
Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.
Interested in more tips and information?
|
|
Thank you for your PR! When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:
This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖 Follow this PR Review Process:
If you have questions about anything, reach out in #jetpack-developers for guidance! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes a pagination error that occurs when removing items from the forms inbox, spam, or trash views. When the last items on a page are removed, the user should be navigated to the last valid page rather than remaining on a now-empty invalid page.
Key Changes
- Added
invalidateCacheAndNavigatehelper function to handle cache invalidation and page navigation after item removal - Integrated the helper into
markAsSpamAction,markAsNotSpamAction,restoreAction,moveToTrashAction, anddeleteAction - The helper calculates the new total pages based on remaining item counts and navigates to the last valid page if needed
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| projects/packages/forms/src/dashboard/inbox/dataviews/actions.js | Added invalidateCacheAndNavigate helper function and integrated it into all item removal actions to prevent invalid page states |
| projects/packages/forms/changelog/fix-forms-second-page | Added changelog entry documenting the pagination fix |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| statusBeingRemovedFrom | ||
| ) => { | ||
| // Invalidate entity records cache for current view | ||
| registry | ||
| .dispatch( coreStore ) | ||
| .invalidateResolution( 'getEntityRecords', [ 'postType', 'feedback', currentQuery ] ); | ||
|
|
||
| // Invalidate counts to ensure accurate totals | ||
| registry.dispatch( dashboardStore ).invalidateCounts(); | ||
|
|
||
| // Navigate to correct page if current page will be invalid | ||
| const { getTrashCount, getSpamCount, getInboxCount } = registry.select( dashboardStore ); | ||
| const { setCurrentQuery } = registry.dispatch( dashboardStore ); | ||
|
|
||
| // Get the appropriate count based on which status we're removing from | ||
| const countGetters = { | ||
| trash: getTrashCount, | ||
| spam: getSpamCount, | ||
| inbox: getInboxCount, | ||
| }; | ||
| const remainingCount = countGetters[ statusBeingRemovedFrom ]( queryParams ); | ||
|
|
Copilot
AI
Nov 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The count selectors are called immediately after invalidating counts, which returns the stale optimistic counts from the state cache rather than the actual remaining count after item removal. This causes incorrect pagination calculations. The optimistic count updates happen before items are removed, so the counts used here don't reflect the actual post-removal state. Consider calculating the remaining count by subtracting the number of successfully removed items from the current count, or calling the selectors before invalidation to use the optimistic values intentionally.
| statusBeingRemovedFrom | |
| ) => { | |
| // Invalidate entity records cache for current view | |
| registry | |
| .dispatch( coreStore ) | |
| .invalidateResolution( 'getEntityRecords', [ 'postType', 'feedback', currentQuery ] ); | |
| // Invalidate counts to ensure accurate totals | |
| registry.dispatch( dashboardStore ).invalidateCounts(); | |
| // Navigate to correct page if current page will be invalid | |
| const { getTrashCount, getSpamCount, getInboxCount } = registry.select( dashboardStore ); | |
| const { setCurrentQuery } = registry.dispatch( dashboardStore ); | |
| // Get the appropriate count based on which status we're removing from | |
| const countGetters = { | |
| trash: getTrashCount, | |
| spam: getSpamCount, | |
| inbox: getInboxCount, | |
| }; | |
| const remainingCount = countGetters[ statusBeingRemovedFrom ]( queryParams ); | |
| statusBeingRemovedFrom, | |
| numRemoved | |
| ) => { | |
| // Get the appropriate count based on which status we're removing from, before invalidation | |
| const { getTrashCount, getSpamCount, getInboxCount } = registry.select( dashboardStore ); | |
| const { setCurrentQuery } = registry.dispatch( dashboardStore ); | |
| const countGetters = { | |
| trash: getTrashCount, | |
| spam: getSpamCount, | |
| inbox: getInboxCount, | |
| }; | |
| const currentCount = countGetters[ statusBeingRemovedFrom ]( queryParams ); | |
| const remainingCount = Math.max(0, currentCount - numRemoved); | |
| // Invalidate entity records cache for current view | |
| registry | |
| .dispatch( coreStore ) | |
| .invalidateResolution( 'getEntityRecords', [ 'postType', 'feedback', currentQuery ] ); | |
| // Invalidate counts to ensure accurate totals | |
| registry.dispatch( dashboardStore ).invalidateCounts(); |
|
|
||
| // If there is at least one successful update, invalidate the cache and navigate if needed | ||
| if ( itemsUpdated.length ) { | ||
| invalidateCacheAndNavigate( registry, getCurrentQuery(), queryParams, 'inbox' ); |
Copilot
AI
Nov 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The statusBeingRemovedFrom parameter is hardcoded to 'inbox', but moveToTrashAction can be triggered from items with any status (see isEligible: item => item.status !== 'trash' at line 358). Items could be in 'spam' or 'publish' status. This should use the actual status of the items being moved, not a hardcoded value, otherwise pagination calculations will use the wrong count.
| invalidateCacheAndNavigate( registry, getCurrentQuery(), queryParams, 'inbox' ); | |
| // Use the actual status of the items being moved, not a hardcoded value | |
| invalidateCacheAndNavigate( registry, getCurrentQuery(), queryParams, items[0]?.status ); |
adfc176 to
1272c21
Compare
Code Coverage SummaryCoverage changed in 1 file.
Full summary · PHP report · JS report If appropriate, add one of these labels to override the failing coverage check:
Covered by non-unit tests
|
Currently when you remove items from the last page, the request for content on the page returns a 400 error which results the state of the page freezing.
This is fixed by making sure that we invalidate and navigate away from the last page if we notice that there is nothing on the last page.
Before:
Screen.Recording.2025-11-01.at.12.57.04.PM.mov
After:
Screen.Recording.2025-11-01.at.12.58.43.PM.mov
Fixes FORMS-361
Proposed changes:
Other information:
Jetpack product discussion
See FORMS-361
Does this pull request change what data or activity we track or use?
No
Testing instructions:
Now switch to this branch and follow the same steps as above.
Notice that you end up on the correct page as expected.