From 2f1aa42aeb36574f7e40f6469187110014474631 Mon Sep 17 00:00:00 2001 From: Marin Atanasov Date: Thu, 2 Feb 2023 13:27:39 +0200 Subject: [PATCH 1/2] Block Editor: Optimize __unstableGetVisibleBlocks() --- .../block-editor/src/components/block-list/index.js | 2 +- packages/block-editor/src/store/selectors.js | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index 2193cedcf1c108..d71b47b3caca44 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -168,7 +168,7 @@ function Items( { value={ // Only provide data asynchronously if the block is // not visible and not selected. - ! visibleBlocks.has( clientId ) && + ! visibleBlocks.includes( clientId ) && ! selectedBlocks.includes( clientId ) } > diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 5b70183acccf2a..888c90b0eb7dc1 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2722,11 +2722,13 @@ export function isBlockVisible( state, clientId ) { */ export const __unstableGetVisibleBlocks = createSelector( ( state ) => { - return new Set( - Object.keys( state.blockVisibility ).filter( - ( key ) => state.blockVisibility[ key ] - ) + const visibleBlocks = Object.keys( state.blockVisibility ).filter( + ( key ) => state.blockVisibility[ key ] ); + if ( visibleBlocks.length === 0 ) { + return EMPTY_ARRAY; + } + return visibleBlocks; }, ( state ) => [ state.blockVisibility ] ); From bc5e01f3625c260b65e91392cf721c2bccfa0cdd Mon Sep 17 00:00:00 2001 From: Marin Atanasov Date: Thu, 2 Feb 2023 15:02:13 +0200 Subject: [PATCH 2/2] Change it back to a Set --- .../src/components/block-list/index.js | 2 +- packages/block-editor/src/store/selectors.js | 21 +++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index d71b47b3caca44..2193cedcf1c108 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -168,7 +168,7 @@ function Items( { value={ // Only provide data asynchronously if the block is // not visible and not selected. - ! visibleBlocks.includes( clientId ) && + ! visibleBlocks.has( clientId ) && ! selectedBlocks.includes( clientId ) } > diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 888c90b0eb7dc1..543da7dd1debb5 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -55,6 +55,17 @@ const MILLISECONDS_PER_WEEK = 7 * 24 * 3600 * 1000; */ const EMPTY_ARRAY = []; +/** + * Shared reference to an empty Set for cases where it is important to avoid + * returning a new Set reference on every invocation, as in a connected or + * other pure component which performs `shouldComponentUpdate` check on props. + * This should be used as a last resort, since the normalized data should be + * maintained by the reducer result in state. + * + * @type {Set} + */ +const EMPTY_SET = new Set(); + /** * Returns a block's name given its client ID, or null if no block exists with * the client ID. @@ -2722,11 +2733,13 @@ export function isBlockVisible( state, clientId ) { */ export const __unstableGetVisibleBlocks = createSelector( ( state ) => { - const visibleBlocks = Object.keys( state.blockVisibility ).filter( - ( key ) => state.blockVisibility[ key ] + const visibleBlocks = new Set( + Object.keys( state.blockVisibility ).filter( + ( key ) => state.blockVisibility[ key ] + ) ); - if ( visibleBlocks.length === 0 ) { - return EMPTY_ARRAY; + if ( visibleBlocks.size === 0 ) { + return EMPTY_SET; } return visibleBlocks; },