diff --git a/docs/designers-developers/developers/data/data-core-block-editor.md b/docs/designers-developers/developers/data/data-core-block-editor.md index 8fc4996c96df3b..022fcf2cd2db93 100644 --- a/docs/designers-developers/developers/data/data-core-block-editor.md +++ b/docs/designers-developers/developers/data/data-core-block-editor.md @@ -253,6 +253,8 @@ _Returns_ Returns all block objects for the current post being edited as an array in the order they appear in the post. +Does not include InnerBlocks of blocks which control their own InnerBlocks. + Note: It's important to memoize this selector to avoid return a new instance on each call @@ -260,6 +262,7 @@ _Parameters_ - _state_ `Object`: Editor state. - _rootClientId_ `?string`: Optional root client ID of block list. +- _withControlledInnerBlocks_ `?boolean`: If true, include inner blocks that are controlled by their parent. _Returns_ @@ -307,6 +310,10 @@ _Returns_ - `?string`: Client ID of block selection start. +# **getBlockWithoutControlledInnerBlocks** + +Undocumented declaration. + # **getClientIdsOfDescendants** Returns an array containing the clientIds of all descendants diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index 0f68df3b37c059..00ecabceebe491 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -248,9 +248,7 @@ const withBlockCache = ( reducer ) => ( state = {}, action ) => { do { result.push( current ); current = state.parents[ current ]; - // We do not want to include the parent clientID if its inner - // blocks are controlled so that its cache key stay the same. - } while ( current && ! state.controlledInnerBlocks[ current ] ); + } while ( current ); return result; }, [] ); }; @@ -267,10 +265,7 @@ const withBlockCache = ( reducer ) => ( state = {}, action ) => { const updatedBlockUids = keys( flattenBlocks( action.blocks ) ); // Only include the rootClientId if its inner blocks are uncontrolled. - if ( - action.rootClientId && - ! state.controlledInnerBlocks[ action.rootClientId ] - ) { + if ( action.rootClientId ) { updatedBlockUids.push( action.rootClientId ); } newState.cache = { diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 244fce9b62a4c9..45acdc6d9c3343 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -123,6 +123,9 @@ export function isBlockValid( state, clientId ) { * @return {Object?} Block attributes. */ export function getBlockAttributes( state, clientId ) { + if ( ! state.blocks ) { + return null; + } const block = state.blocks.byClientId[ clientId ]; if ( ! block ) { return null; @@ -137,8 +140,8 @@ export function getBlockAttributes( state, clientId ) { * is not the block's registration settings, which must be retrieved from the * blocks module registration store. * - * @param {Object} state Editor state. - * @param {string} clientId Block client ID. + * @param {Object} state Editor state. + * @param {string} clientId Block client ID. * * @return {Object} Parsed block object. */ @@ -152,9 +155,7 @@ export const getBlock = createSelector( return { ...block, attributes: getBlockAttributes( state, clientId ), - innerBlocks: areInnerBlocksControlled( state, clientId ) - ? EMPTY_ARRAY - : getBlocks( state, clientId ), + innerBlocks: getBlocks( state, clientId ), }; }, ( state, clientId ) => [ @@ -167,6 +168,28 @@ export const getBlock = createSelector( ] ); +export const getBlockWithoutControlledInnerBlocks = createSelector( + ( state, clientId ) => { + const block = state.blocks.byClientId[ clientId ]; + if ( ! block ) { + return null; + } + + return { + ...block, + attributes: getBlockAttributes( state, clientId ), + innerBlocks: areInnerBlocksControlled( state, clientId ) + ? EMPTY_ARRAY + : getBlocks( state, clientId, false ), + }; + }, + ( state, clientId ) => [ + state.blocks.controlledInnerBlocks[ clientId ] + ? getBlockAttributes( clientId ) + : state.blocks.cache[ clientId ], + ] +); + export const __unstableGetBlockWithoutInnerBlocks = createSelector( ( state, clientId ) => { const block = state.blocks.byClientId[ clientId ]; @@ -189,18 +212,24 @@ export const __unstableGetBlockWithoutInnerBlocks = createSelector( * Returns all block objects for the current post being edited as an array in * the order they appear in the post. * + * Does not include InnerBlocks of blocks which control their own InnerBlocks. + * * Note: It's important to memoize this selector to avoid return a new instance * on each call * * @param {Object} state Editor state. * @param {?string} rootClientId Optional root client ID of block list. + * @param {?boolean} withControlledInnerBlocks If true, include inner blocks that + * are controlled by their parent. * * @return {Object[]} Post blocks. */ export const getBlocks = createSelector( - ( state, rootClientId ) => { + ( state, rootClientId, withControlledInnerBlocks = true ) => { return map( getBlockOrder( state, rootClientId ), ( clientId ) => - getBlock( state, clientId ) + withControlledInnerBlocks + ? getBlock( state, clientId ) + : getBlockWithoutControlledInnerBlocks( state, clientId ) ); }, ( state ) => [