Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only check for 'other' block control slot in useHasAnyBlockControls #59884

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,27 @@
* WordPress dependencies
*/
import { __experimentalUseSlotFills as useSlotFills } from '@wordpress/components';
import warning from '@wordpress/warning';

/**
* Internal dependencies
*/
import groups from './groups';

export function useHasAnyBlockControls() {
let hasAnyBlockControls = false;
for ( const group in groups ) {
// It is safe to violate the rules of hooks here as the `groups` object
// is static and will not change length between renders. Do not return
// early as that will cause the hook to be called a different number of
// times between renders.
// eslint-disable-next-line react-hooks/rules-of-hooks
if ( useHasBlockControls( group ) ) {
hasAnyBlockControls = true;
}
}
return hasAnyBlockControls;
}

export function useHasBlockControls( group = 'default' ) {
const Slot = groups[ group ]?.Slot;
/**
* We only care about the "other" slot here.
* This check is specifically for allowing the Replace
* <MediaReplaceFlow /> on featured images and images
* within content locked areas.
* https://github.com/WordPress/gutenberg/pull/53410
*
* TODO: Remove this hook, as having a toolbar with only a Replace button is a
* misuse of the toolbar.
*/
export function useHasOtherBlockControls() {
const Slot = groups.other?.Slot;
const fills = useSlotFills( Slot?.__unstableName );
if ( ! Slot ) {
warning( `Unknown BlockControls group "${ group }" provided.` );
return null;
return false;
}
return !! fills?.length;
}
10 changes: 5 additions & 5 deletions packages/block-editor/src/components/block-toolbar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,6 @@ export function PrivateBlockToolbar( {

const isLargeViewport = ! useViewportMatch( 'medium', '<' );

const hasBlockToolbar = useHasBlockToolbar();
if ( ! hasBlockToolbar ) {
return null;
}

const isMultiToolbar = blockClientIds.length > 1;
const isSynced =
isReusableBlock( blockType ) || isTemplatePart( blockType );
Expand Down Expand Up @@ -242,6 +237,11 @@ export function PrivateBlockToolbar( {
* @param {string} props.variant Style variant of the toolbar, also passed to the Dropdowns rendered from Block Toolbar Buttons.
*/
export default function BlockToolbar( { hideDragHandle, variant } ) {
const hasBlockToolbar = useHasBlockToolbar();
if ( ! hasBlockToolbar ) {
return null;
}
Comment on lines +240 to +243
Copy link
Contributor Author

@jeryj jeryj Mar 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving this check to before the <PrivateBlockToolbar /> avoids making an unnecessary useSelect, as if this is false then we know the toolbar will not render.


return (
<PrivateBlockToolbar
hideDragHandle={ hideDragHandle }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,26 @@ import { getBlockType, hasBlockSupport } from '@wordpress/blocks';
* Internal dependencies
*/
import { store as blockEditorStore } from '../../store';
import { useHasAnyBlockControls } from '../block-controls/use-has-block-controls';

/**
* Returns true if the block toolbar should be shown.
*
* @return {boolean} Whether the block toolbar component will be rendered.
*/
export function useHasBlockToolbar() {
const hasAnyBlockControls = useHasAnyBlockControls();
return useSelect(
( select ) => {
const {
getBlockEditingMode,
getBlockName,
getSelectedBlockClientIds,
} = select( blockEditorStore );
return useSelect( ( select ) => {
const { getBlockName, getSelectedBlockClientIds } =
select( blockEditorStore );

const selectedBlockClientIds = getSelectedBlockClientIds();
const selectedBlockClientId = selectedBlockClientIds[ 0 ];
const isDefaultEditingMode =
getBlockEditingMode( selectedBlockClientId ) === 'default';
const blockType =
selectedBlockClientId &&
getBlockType( getBlockName( selectedBlockClientId ) );
const isToolbarEnabled =
blockType &&
hasBlockSupport( blockType, '__experimentalToolbar', true );
const selectedBlockClientIds = getSelectedBlockClientIds();
const selectedBlockClientId = selectedBlockClientIds[ 0 ];
const blockType =
selectedBlockClientId &&
getBlockType( getBlockName( selectedBlockClientId ) );
const isToolbarEnabled =
blockType &&
hasBlockSupport( blockType, '__experimentalToolbar', true );

if (
! isToolbarEnabled ||
( ! isDefaultEditingMode && ! hasAnyBlockControls )
) {
return false;
}

return true;
},
[ hasAnyBlockControls ]
);
return isToolbarEnabled;
}, [] );
}
Loading