From 7f2ea04bb799e134fcef3e41763aaedb750ad351 Mon Sep 17 00:00:00 2001 From: Robert Anderson Date: Mon, 19 Jun 2023 13:53:27 +1000 Subject: [PATCH] Reduce number of List View re-renders while typing (#51518) * Add getClientIdsTreeWithBlockEditingMode() * Rename getClientIdsTreeWithBlockEditingMode -> getListViewClientIdsTree --- .../list-view/use-list-view-client-ids.js | 23 +-- .../src/store/private-selectors.js | 34 ++++ packages/block-editor/src/store/selectors.js | 35 +++- .../src/store/test/private-selectors.js | 174 +++++++++++++++++- .../block-editor/src/store/test/selectors.js | 1 + 5 files changed, 239 insertions(+), 28 deletions(-) diff --git a/packages/block-editor/src/components/list-view/use-list-view-client-ids.js b/packages/block-editor/src/components/list-view/use-list-view-client-ids.js index 8b989591802fa..d51412fdf2c3d 100644 --- a/packages/block-editor/src/components/list-view/use-list-view-client-ids.js +++ b/packages/block-editor/src/components/list-view/use-list-view-client-ids.js @@ -16,31 +16,14 @@ export default function useListViewClientIds( { blocks, rootClientId } ) { const { getDraggedBlockClientIds, getSelectedBlockClientIds, - __unstableGetClientIdsTree, - getBlockEditingMode, + getListViewClientIdsTree, } = unlock( select( blockEditorStore ) ); - const removeDisabledBlocks = ( tree ) => { - return tree.flatMap( ( { clientId, innerBlocks, ...rest } ) => { - if ( getBlockEditingMode( clientId ) === 'disabled' ) { - return removeDisabledBlocks( innerBlocks ); - } - return [ - { - clientId, - innerBlocks: removeDisabledBlocks( innerBlocks ), - ...rest, - }, - ]; - } ); - }; - return { selectedClientIds: getSelectedBlockClientIds(), draggedClientIds: getDraggedBlockClientIds(), - clientIdsTree: removeDisabledBlocks( - blocks ?? __unstableGetClientIdsTree( rootClientId ) - ), + clientIdsTree: + blocks ?? getListViewClientIdsTree( rootClientId ), }; }, [ blocks, rootClientId ] diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index ff85b4fb3f20b..c250b649569f0 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -135,3 +135,37 @@ export const isBlockSubtreeDisabled = createSelector( }, ( state ) => [ state.blockEditingModes, state.blocks.parents ] ); + +/** + * Returns a tree of block objects with only clientID and innerBlocks set. + * Blocks with a 'disabled' editing mode are not included. + * + * @param {Object} state Global application state. + * @param {?string} rootClientId Optional root client ID of block list. + * + * @return {Object[]} Tree of block objects with only clientID and innerBlocks set. + */ +export const getListViewClientIdsTree = createSelector( + ( state, rootClientId = '' ) => { + return getBlockOrder( state, rootClientId ).flatMap( ( clientId ) => { + if ( getBlockEditingMode( state, clientId ) !== 'disabled' ) { + return [ + { + clientId, + innerBlocks: getListViewClientIdsTree( + state, + clientId + ), + }, + ]; + } + return getListViewClientIdsTree( state, clientId ); + } ); + }, + ( state ) => [ + state.blocks.order, + state.blockEditingModes, + state.settings.templateLock, + state.blockListSettings, + ] +); diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 128b167f69761..1616a2fde8b1b 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -187,16 +187,27 @@ export function getBlocks( state, rootClientId ) { * Returns a stripped down block object containing only its client ID, * and its inner blocks' client IDs. * + * @deprecated + * * @param {Object} state Editor state. * @param {string} clientId Client ID of the block to get. * * @return {Object} Client IDs of the post blocks. */ export const __unstableGetClientIdWithClientIdsTree = createSelector( - ( state, clientId ) => ( { - clientId, - innerBlocks: __unstableGetClientIdsTree( state, clientId ), - } ), + ( state, clientId ) => { + deprecated( + "wp.data.select( 'core/block-editor' ).__unstableGetClientIdWithClientIdsTree", + { + since: '6.3', + version: '6.5', + } + ); + return { + clientId, + innerBlocks: __unstableGetClientIdsTree( state, clientId ), + }; + }, ( state ) => [ state.blocks.order ] ); @@ -205,16 +216,26 @@ export const __unstableGetClientIdWithClientIdsTree = createSelector( * given root, consisting of stripped down block objects containing only * their client IDs, and their inner blocks' client IDs. * + * @deprecated + * * @param {Object} state Editor state. * @param {?string} rootClientId Optional root client ID of block list. * * @return {Object[]} Client IDs of the post blocks. */ export const __unstableGetClientIdsTree = createSelector( - ( state, rootClientId = '' ) => - getBlockOrder( state, rootClientId ).map( ( clientId ) => + ( state, rootClientId = '' ) => { + deprecated( + "wp.data.select( 'core/block-editor' ).__unstableGetClientIdsTree", + { + since: '6.3', + version: '6.5', + } + ); + return getBlockOrder( state, rootClientId ).map( ( clientId ) => __unstableGetClientIdWithClientIdsTree( state, clientId ) - ), + ); + }, ( state ) => [ state.blocks.order ] ); diff --git a/packages/block-editor/src/store/test/private-selectors.js b/packages/block-editor/src/store/test/private-selectors.js index ecae342317ce1..ab0d4b11c5bf4 100644 --- a/packages/block-editor/src/store/test/private-selectors.js +++ b/packages/block-editor/src/store/test/private-selectors.js @@ -11,6 +11,7 @@ import { getLastInsertedBlocksClientIds, getBlockEditingMode, isBlockSubtreeDisabled, + getListViewClientIdsTree, } from '../private-selectors'; jest.mock( '@wordpress/data/src/select', () => ( { @@ -74,7 +75,13 @@ describe( 'private selectors', () => { [ 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', {} ], // | | Paragraph ] ), order: new Map( [ - [ '', [ '6cf70164-9097-4460-bcbf-200560546988' ] ], + [ + '', + [ + '6cf70164-9097-4460-bcbf-200560546988', + 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', + ], + ], [ '6cf70164-9097-4460-bcbf-200560546988', [] ], [ 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', @@ -382,4 +389,169 @@ describe( 'private selectors', () => { } ); } ); } ); + + describe( 'getListViewClientIdsTree', () => { + const baseState = { + settings: {}, + blocks: { + byClientId: new Map( [ + [ '6cf70164-9097-4460-bcbf-200560546988', {} ], // Header + [ 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', {} ], // Group + [ 'b26fc763-417d-4f01-b81c-2ec61e14a972', {} ], // | Post Title + [ '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f', {} ], // | Post Content + [ 'b3247f75-fd94-4fef-97f9-5bfd162cc416', {} ], // | | Paragraph + [ 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', {} ], // | | Paragraph + ] ), + order: new Map( [ + [ + '', + [ + '6cf70164-9097-4460-bcbf-200560546988', + 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', + ], + ], + [ '6cf70164-9097-4460-bcbf-200560546988', [] ], + [ + 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', + [ + 'b26fc763-417d-4f01-b81c-2ec61e14a972', + '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f', + ], + ], + [ 'b26fc763-417d-4f01-b81c-2ec61e14a972', [] ], + [ + '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f', + [ + 'b3247f75-fd94-4fef-97f9-5bfd162cc416', + 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', + ], + ], + [ 'b3247f75-fd94-4fef-97f9-5bfd162cc416', [] ], + [ 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', [] ], + ] ), + parents: new Map( [ + [ '6cf70164-9097-4460-bcbf-200560546988', '' ], + [ 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', '' ], + [ + 'b26fc763-417d-4f01-b81c-2ec61e14a972', + 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', + ], + [ + '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f', + 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', + ], + [ + 'b3247f75-fd94-4fef-97f9-5bfd162cc416', + '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f', + ], + [ + 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', + '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f', + ], + ] ), + }, + blockListSettings: { + 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337': {}, + '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f': {}, + }, + }; + + it( 'should return tree containing only clientId and innerBlocks', () => { + const state = { + ...baseState, + blockEditingModes: new Map( [] ), + }; + expect( getListViewClientIdsTree( state ) ).toEqual( [ + { + clientId: '6cf70164-9097-4460-bcbf-200560546988', + innerBlocks: [], + }, + { + clientId: 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', + innerBlocks: [ + { + clientId: 'b26fc763-417d-4f01-b81c-2ec61e14a972', + innerBlocks: [], + }, + { + clientId: '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f', + innerBlocks: [ + { + clientId: + 'b3247f75-fd94-4fef-97f9-5bfd162cc416', + innerBlocks: [], + }, + { + clientId: + 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', + innerBlocks: [], + }, + ], + }, + ], + }, + ] ); + } ); + + it( 'should return a subtree when rootBlockClientId is given', () => { + const state = { + ...baseState, + blockEditingModes: new Map( [] ), + }; + expect( + getListViewClientIdsTree( + state, + 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337' + ) + ).toEqual( [ + { + clientId: 'b26fc763-417d-4f01-b81c-2ec61e14a972', + innerBlocks: [], + }, + { + clientId: '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f', + innerBlocks: [ + { + clientId: 'b3247f75-fd94-4fef-97f9-5bfd162cc416', + innerBlocks: [], + }, + { + clientId: 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', + innerBlocks: [], + }, + ], + }, + ] ); + } ); + + it( 'should filter out disabled blocks', () => { + const state = { + ...baseState, + blockEditingModes: new Map( [ + [ '', 'disabled' ], + [ 'b26fc763-417d-4f01-b81c-2ec61e14a972', 'contentOnly' ], + [ '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f', 'contentOnly' ], + ] ), + }; + expect( getListViewClientIdsTree( state ) ).toEqual( [ + { + clientId: 'b26fc763-417d-4f01-b81c-2ec61e14a972', + innerBlocks: [], + }, + { + clientId: '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f', + innerBlocks: [ + { + clientId: 'b3247f75-fd94-4fef-97f9-5bfd162cc416', + innerBlocks: [], + }, + { + clientId: 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', + innerBlocks: [], + }, + ], + }, + ] ); + } ); + } ); } ); diff --git a/packages/block-editor/src/store/test/selectors.js b/packages/block-editor/src/store/test/selectors.js index 5cc17fc08b314..dca9b847bc5a2 100644 --- a/packages/block-editor/src/store/test/selectors.js +++ b/packages/block-editor/src/store/test/selectors.js @@ -4734,6 +4734,7 @@ describe( '__unstableGetClientIdWithClientIdsTree', () => { { clientId: 'baz', innerBlocks: [] }, ], } ); + expect( console ).toHaveWarned(); } ); } ); describe( '__unstableGetClientIdsTree', () => {