From 3fc9c5ef24e016e34f87e5feed70dd4c1774c5a1 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Tue, 30 Jan 2024 08:24:13 +0200 Subject: [PATCH] Block editor: optimise getGlobalBlockCount/getClientIdsWithDescendants (#58356) --- .../data/data-core-block-editor.md | 2 +- packages/block-editor/src/store/selectors.js | 62 ++++++++++--------- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md index b03e905d166bc..eaffc0a875ca3 100644 --- a/docs/reference-guides/data/data-core-block-editor.md +++ b/docs/reference-guides/data/data-core-block-editor.md @@ -486,7 +486,7 @@ Returns an array containing the clientIds of all descendants of the blocks given _Parameters_ - _state_ `Object`: Global application state. -- _clientIds_ `string|string[]`: Client ID(s) for which descendant blocks are to be returned. +- _rootIds_ `string|string[]`: Client ID(s) for which descendant blocks are to be returned. _Returns_ diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 7964f86a5e782..3475e2b5351c8 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -252,24 +252,37 @@ export const __unstableGetClientIdsTree = createSelector( * given. Returned ids are ordered first by the order of the ids given, then * by the order that they appear in the editor. * - * @param {Object} state Global application state. - * @param {string|string[]} clientIds Client ID(s) for which descendant blocks are to be returned. + * @param {Object} state Global application state. + * @param {string|string[]} rootIds Client ID(s) for which descendant blocks are to be returned. * * @return {Array} Client IDs of descendants. */ export const getClientIdsOfDescendants = createSelector( - ( state, clientIds ) => { - const givenIds = Array.isArray( clientIds ) ? clientIds : [ clientIds ]; - const collectedIds = []; - for ( const givenId of givenIds ) { - for ( const descendantId of getBlockOrder( state, givenId ) ) { - collectedIds.push( - descendantId, - ...getClientIdsOfDescendants( state, descendantId ) - ); + ( state, rootIds ) => { + rootIds = Array.isArray( rootIds ) ? [ ...rootIds ] : [ rootIds ]; + const ids = []; + + // Add the descendants of the root blocks first. + for ( const rootId of rootIds ) { + const order = state.blocks.order.get( rootId ); + if ( order ) { + ids.push( ...order ); + } + } + + let index = 0; + + // Add the descendants of the descendants, recursively. + while ( index < ids.length ) { + const id = ids[ index ]; + const order = state.blocks.order.get( id ); + if ( order ) { + ids.splice( index + 1, 0, ...order ); } + index++; } - return collectedIds; + + return ids; }, ( state ) => [ state.blocks.order ] ); @@ -283,19 +296,8 @@ export const getClientIdsOfDescendants = createSelector( * * @return {Array} ids of top-level and descendant blocks. */ -export const getClientIdsWithDescendants = createSelector( - ( state ) => { - const collectedIds = []; - for ( const topLevelId of getBlockOrder( state ) ) { - collectedIds.push( - topLevelId, - ...getClientIdsOfDescendants( state, topLevelId ) - ); - } - return collectedIds; - }, - ( state ) => [ state.blocks.order ] -); +export const getClientIdsWithDescendants = ( state ) => + getClientIdsOfDescendants( state, '' ); /** * Returns the total number of blocks, or the total number of blocks with a specific name in a post. @@ -312,10 +314,14 @@ export const getGlobalBlockCount = createSelector( if ( ! blockName ) { return clientIds.length; } - return clientIds.reduce( ( accumulator, clientId ) => { + let count = 0; + for ( const clientId of clientIds ) { const block = state.blocks.byClientId.get( clientId ); - return block.name === blockName ? accumulator + 1 : accumulator; - }, 0 ); + if ( block.name === blockName ) { + count++; + } + } + return count; }, ( state ) => [ state.blocks.order, state.blocks.byClientId ] );