diff --git a/packages/block-editor/src/components/inner-blocks/get-block-context.js b/packages/block-editor/src/components/inner-blocks/get-block-context.js deleted file mode 100644 index 295ef380d3808d..00000000000000 --- a/packages/block-editor/src/components/inner-blocks/get-block-context.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * External dependencies - */ -import { mapValues } from 'lodash'; - -/** - * Block context cache, implemented as a WeakMap mapping block types to a - * WeakMap mapping attributes object to context value. - * - * @type {WeakMap>} - */ -const BLOCK_CONTEXT_CACHE = new WeakMap(); - -/** - * Returns a cached context object value for a given set of attributes for the - * block type. - * - * @param {Record} attributes Block attributes object. - * @param {WPBlockType} blockType Block type settings. - * - * @return {Record} Context value. - */ -export default function getBlockContext( attributes, blockType ) { - if ( ! BLOCK_CONTEXT_CACHE.has( blockType ) ) { - BLOCK_CONTEXT_CACHE.set( blockType, new WeakMap() ); - } - - const blockTypeCache = BLOCK_CONTEXT_CACHE.get( blockType ); - if ( ! blockTypeCache.has( attributes ) ) { - const context = mapValues( - blockType.providesContext, - ( attributeName ) => attributes[ attributeName ] - ); - - blockTypeCache.set( attributes, context ); - } - - return blockTypeCache.get( attributes ); -} diff --git a/packages/block-editor/src/components/inner-blocks/index.js b/packages/block-editor/src/components/inner-blocks/index.js index 0512569fb3f42d..6be5ae690f7243 100644 --- a/packages/block-editor/src/components/inner-blocks/index.js +++ b/packages/block-editor/src/components/inner-blocks/index.js @@ -11,7 +11,6 @@ import { forwardRef, useMemo } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; import { getBlockSupport, - getBlockType, store as blocksStore, __unstableGetInnerBlocksProps as getInnerBlocksProps, } from '@wordpress/blocks'; @@ -23,7 +22,7 @@ import ButtonBlockAppender from './button-block-appender'; import DefaultBlockAppender from './default-block-appender'; import useNestedSettingsUpdate from './use-nested-settings-update'; import useInnerBlockTemplateSync from './use-inner-block-template-sync'; -import getBlockContext from './get-block-context'; +import useBlockContext from './use-block-context'; import { BlockListItems } from '../block-list'; import { BlockContextProvider } from '../block-context'; import { useBlockEditContext } from '../block-edit/context'; @@ -75,28 +74,10 @@ function UncontrolledInnerBlocks( props ) { templateInsertUpdatesSelection ); - const { context, name } = useSelect( + const context = useBlockContext( clientId ); + const name = useSelect( ( select ) => { - const block = select( blockEditorStore ).getBlock( clientId ); - - // This check is here to avoid the Redux zombie bug where a child subscription - // is called before a parent, causing potential JS errors when the child has been removed. - if ( ! block ) { - return {}; - } - - const blockType = getBlockType( block.name ); - - if ( - Object.keys( blockType?.providesContext ?? {} ).length === 0 - ) { - return { name: block.name }; - } - - return { - context: getBlockContext( block.attributes, blockType ), - name: block.name, - }; + return select( blockEditorStore ).getBlock( clientId )?.name; }, [ clientId ] ); diff --git a/packages/block-editor/src/components/inner-blocks/index.native.js b/packages/block-editor/src/components/inner-blocks/index.native.js index 2b5ffe01aaf08c..3ba3b8e8321a2b 100644 --- a/packages/block-editor/src/components/inner-blocks/index.native.js +++ b/packages/block-editor/src/components/inner-blocks/index.native.js @@ -1,11 +1,7 @@ /** * WordPress dependencies */ -import { useSelect } from '@wordpress/data'; -import { - getBlockType, - __unstableGetInnerBlocksProps as getInnerBlocksProps, -} from '@wordpress/blocks'; +import { __unstableGetInnerBlocksProps as getInnerBlocksProps } from '@wordpress/blocks'; import { useRef } from '@wordpress/element'; /** @@ -15,7 +11,7 @@ import ButtonBlockAppender from './button-block-appender'; import DefaultBlockAppender from './default-block-appender'; import useNestedSettingsUpdate from './use-nested-settings-update'; import useInnerBlockTemplateSync from './use-inner-block-template-sync'; -import getBlockContext from './get-block-context'; +import useBlockContext from './use-block-context'; /** * Internal dependencies @@ -26,7 +22,6 @@ import { useBlockEditContext } from '../block-edit/context'; import useBlockSync from '../provider/use-block-sync'; import { BlockContextProvider } from '../block-context'; import { defaultLayout, LayoutProvider } from '../block-list/layout'; -import { store as blockEditorStore } from '../../store'; /** * This hook is used to lightly mark an element as an inner blocks wrapper @@ -100,10 +95,7 @@ function UncontrolledInnerBlocks( props ) { useCompactList, } = props; - const block = useSelect( - ( select ) => select( blockEditorStore ).getBlock( clientId ), - [ clientId ] - ) || { innerBlocks: [] }; + const context = useBlockContext( clientId ); useNestedSettingsUpdate( clientId, allowedBlocks, templateLock ); @@ -116,43 +108,31 @@ function UncontrolledInnerBlocks( props ) { const BlockListComponent = useCompactList ? BlockListCompact : BlockList; - let blockList = ( - + return ( + + + + + ); - - // Wrap context provider if (and only if) block has context to provide. - const blockType = getBlockType( block.name ); - if ( blockType && blockType.providesContext ) { - const context = getBlockContext( block.attributes, blockType ); - - blockList = ( - - - { blockList } - - - ); - } - - return blockList; } /** diff --git a/packages/block-editor/src/components/inner-blocks/use-block-context.js b/packages/block-editor/src/components/inner-blocks/use-block-context.js new file mode 100644 index 00000000000000..885f8feda5c6f7 --- /dev/null +++ b/packages/block-editor/src/components/inner-blocks/use-block-context.js @@ -0,0 +1,47 @@ +/** + * WordPress dependencies + */ +import { store as blocksStore } from '@wordpress/blocks'; +import { useSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import { store as blockEditorStore } from '../../store'; + +/** + * Returns a context object for a given block. + * + * @param {string} clientId The block client ID. + * + * @return {Record} Context value. + */ +export default function useBlockContext( clientId ) { + return useSelect( + ( select ) => { + const block = select( blockEditorStore ).getBlock( clientId ); + if ( ! block ) { + return undefined; + } + + const blockType = select( blocksStore ).getBlockType( block.name ); + if ( ! blockType ) { + return undefined; + } + + if ( Object.keys( blockType.providesContext ).length === 0 ) { + return undefined; + } + + return Object.fromEntries( + Object.entries( blockType.providesContext ).map( + ( [ contextName, attributeName ] ) => [ + contextName, + block.attributes[ attributeName ], + ] + ) + ); + }, + [ clientId ] + ); +}