Search code examples
reactjsreact-hookswordpress-gutenberggutenberg-blocks

InnerBlocks with template returning a block count of zero


I'm trying to create a block with an InnerBlocks template. Since the block has a template, the block should always have at least 1 child. If the child count ever reaches 0, then I want to remove this block, since it would be empty.

The issue that I'm running into is that the value of "blockCount" is 0 for a split second when the block is first created, so it's removing itself before it's created. Is this a bug with getBlockCount, or is there a way to wait for the template to populate the InnerBlocks before I check the block count?

Here is my edit function for reference.

edit: props => {
  const { setAttributes } = props
  const { className } = props.attributes
  const { removeBlock } = useDispatch('core/block-editor')
  const { blockCount } = useSelect(select => ({
    blockCount: select('core/block-editor').getBlockCount(props.clientId)
  }))
  if (blockCount === 0) {
    removeBlock(props.clientId)
  }
  return (
    <div className={ className }>
      <InnerBlocks
        allowedBlocks={ ['my/block'] }
        template={ [['my/block']] }
        templateLock={ false }
        renderAppender={ false }
      />
    </div>
  )
}

Solution

  • Solution that was offered on Github (and works well) is to save the block length to a ref and then useEffect to watch for changes, and remove the block if the value returns to 0.

    edit: props => {
      const { setAttributes } = props
      const { className } = props.attributes
      const { removeBlock } = useDispatch('core/block-editor')
      const { blockCount } = useSelect(select => ({
        blockCount: select('core/block-editor').getBlockCount(props.clientId)
      }))
      const previousBlockCount = useRef(blockCount)
      useEffect(() => {
        if (previousBlockCount.current > 0 && blockCount === 0) {
          removeBlock(props.clientId)
        }
        previousBlockCount.current = blockCount
      }, [blockCount, props.clientId])
      return (
        <div className={ className }>
          <InnerBlocks
            allowedBlocks={ ['my/block'] }
            template={ [['my/block']] }
            templateLock={ false }
            renderAppender={ false }
          />
        </div>
      )
    }