2

I'm using isSelected to determine if a block is selected, but I'd also like to know if any innerblocks are selected.

I'm using export default function Edit({ isSelected }) {}

I believe this is done with useSelect but I'm not sure how that works.

2 Answers 2

2

If you only need to know whether or not an inner-block is selected, you can leverage the core/block-editor store's hasSelectedInnerBlock() selector. For example, if using a useSelect() hook in a functional component, that might look as such:

import { useSelect } from '@wordpress/data';

export default function Edit( { isSelected, clientId } ) {
  const is_inner_block_selected = useSelect(
    ( select ) => select( 'core/block-editor' ).hasSelectedInnerBlock( clientId )
  );

  // ...
}

After which you might use a simple isSelected || is_inner_block_selected condition to execute your specific functionality - or some other hook with with a [ isSelected, is_inner_block_selected ] dependency.

Of particular note, you can set the second argument of hasSelectedInnerBlock() to true for a deep check - that is, if you wish to know if any descendant is selected (in cases where you would like to know if the inner blocks themselves may have inner blocks which are selected):

select( 'core/block-editor' ).hasSelectedInnerBlock( clientId, true )
3
  • 2
    For more information on what useSelect()/withSelect() does, I've written an introduction to the functions over here, which may (hopefully!) be of some use. In short, they create a subscription between a component and the state selectors which a component depends on such that when the value a selector retrieves changes, the component will re-render. In this case that means if hasSelectedInnerBlock( clientId ) changes from returning true -> false or vis versa, the component will re-render with the new value.
    – bosco
    Commented Aug 22, 2022 at 18:40
  • Worked perfectly! I'd like to know more about the deep check though. I get what you mean by checking if inner, inner blocks are selected, but not how. Do you mean you'd add === true? Not sure how to code what you mean. Thanks!
    – Elizabeth
    Commented Aug 22, 2022 at 18:49
  • 1
    It would just be .hasSelectedInnerBlock( clientId, true ) :)
    – bosco
    Commented Aug 22, 2022 at 18:50
1

I think @Elizabeth was trying to determine if a child block is selected and also if the block itself is selected. If so, building off of @bosco's example, you can create a utility function, like:

// in a file named useIsSelectedOrChild.js:

/**
 * Self or Child Selected
 *
 * This is essentially isSelected, extended to include if a child
 * block is selected.
 */
import { useSelect } from '@wordpress/data';

const useIsSelectedOrChild = (clientId, isSelected = null) => {
    let isSelectedOrChild = useSelect((select) =>
        select('core/block-editor').hasSelectedInnerBlock(clientId)
    );
    if (!isSelectedOrChild && isSelected !== null) {
        isSelectedOrChild = isSelected;
    }
    return isSelectedOrChild;
};

export default useIsSelectedOrChild;

Then you can simply import it into any blocks you want and reuse it:

import useIsSelectedOrChild from 'useIsSelectedOrChild';

export default function edit( { clientId, isSelected } ) {
  const isSelectedOrChild = useIsSelectedOrChild(clientId, isSelected);
  return (
    <div>Myself or a child is {isSelectedOrChild ? 'selected' : 'deselected'}</div>
  )
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.