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

Core data: Fix wrong store results when page receives less items that what is stored #55832

Merged
merged 2 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions packages/core-data/src/queried-data/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ export function getMergedItemIds( itemIds, nextItemIds, page, perPage ) {

for ( let i = 0; i < size; i++ ) {
// Preserve existing item ID except for subset of range of next items.
// We need to check against the possible maximum upper boundary because
// a page could recieve less items than what was previously stored.
const isInNextItemsRange =
i >= nextItemIdsStartIndex &&
i < nextItemIdsStartIndex + nextItemIds.length;

i >= nextItemIdsStartIndex && i < nextItemIdsStartIndex + perPage;
mergedItemIds[ i ] = isInNextItemsRange
? nextItemIds[ i - nextItemIdsStartIndex ]
: itemIds?.[ i ];
Expand Down
2 changes: 1 addition & 1 deletion packages/core-data/src/queried-data/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function getQueriedItemsUncached( state, query ) {

// Having a target item ID doesn't guarantee that this object has been queried.
if ( ! state.items[ context ]?.hasOwnProperty( itemId ) ) {
return null;
continue;
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure about this change, I wonder if this was there to ensure that we only return values if all the ids of the given query have been fetched.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It doesn't seem like a bad change to me and we do the same with ids in include, but I might be missing some context. Maybe @jsnajdr or @Mamaduka have some input? 🤔

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess my question is: is this change required for this PR. If so, can you explain why/how?

Copy link
Member

Choose a reason for hiding this comment

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

I think I tried to make a similar change in #34034 but eventually reverted it. Unfortunately, I don't have any additional input besides what was shared in that PR.

The lack of higher-level/integration tests here makes it easier for regressions to slip in even when changes are minor.

Copy link
Contributor Author

@ntsekouras ntsekouras Nov 6, 2023

Choose a reason for hiding this comment

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

I guess my question is: is this change required for this PR. If so, can you explain why/how?

In this PR if we have fewer items received, we don't add the previous ones(that was the bug), but instead fill it with undefined. Without this change the query will not return anything. Something I was thinking about was, whether to explicitly check for undefined and continue only in that case.

Copy link
Contributor

Choose a reason for hiding this comment

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

What is the reason for filling with undefined instead of just removing them from the itemIds?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because we need the array(itemIds) to be sparse-like with undefined entries where holes exist, for pagination to work properly. If we don't do that and just remove the item there, my understanding is that can break other queries with different page.

Copy link
Contributor

Choose a reason for hiding this comment

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

So I'm still not sure I understand the real reason, what things would break but regardless it seems safer to only "continue" here if the itemId is undefined like you suggested to minimize the impact of this PR.

}

const item = state.items[ context ][ itemId ];
Expand Down
11 changes: 11 additions & 0 deletions packages/core-data/src/queried-data/test/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@ describe( 'getMergedItemIds', () => {

expect( result ).toEqual( [ 1, 3, 4 ] );
} );
it( 'should update a page properly if less items are provided than previously stored', () => {
let original = deepFreeze( [ 1, 2, 3 ] );
let result = getMergedItemIds( original, [ 1, 2 ], 1, 3 );

expect( result ).toEqual( [ 1, 2 ] );

original = deepFreeze( [ 1, 2, 3, 4, 5, 6 ] );
result = getMergedItemIds( original, [ 9 ], 2, 2 );

expect( result ).toEqual( [ 1, 2, 9, undefined, 5, 6 ] );
} );
} );

describe( 'itemIsComplete', () => {
Expand Down
Loading