Custom WP Block using Inner Blocks crashes editor, doesn’t save content

Explanation of the issues in your code:

  1. The main one which causes the block editor to crash, is because you used InnerBlocks in the save function. You should instead use InnerBlocks.Content.

    See this and this for more details on InnerBlocks usage, accepted props, etc.

  2. As for the getAttribute error, it’s because you did not use useBlockProps in the edit function (which should also be used in the save function).

    And why should you use useBlockProps, is because when you registered the block type in JavaScript (using registerBlockType()), you didn’t set the apiVersion property, hence Gutenberg uses the api_version value (which is 2) you set via PHP (using register_block_type()), and when using the block API version 2, useBlockProps should be used, so that the block is properly wrapped, centered and “clickable”.

So to fix the issues:

  • At the top in your script, replace the const { InnerBlocks } = wp.blockEditor; with:

    const { InnerBlocks, useBlockProps } = wp.blockEditor;
    
  • Use useBlockProps() in the edit function, and useBlockProps.save() and InnerBlocks.Content in the save function:

    edit() {
        const blockProps = useBlockProps( { style: blockStyle } );
    
        return (
            <div { ...blockProps }><InnerBlocks /></div>
        );
    },
    save() {
        const blockProps = useBlockProps.save( { style: blockStyle } );
    
        return (
            <div { ...blockProps }><InnerBlocks.Content /></div>
        );
    }
    

Additional Notes

  • Are you already using the @wordpress/scripts package to build your scripts (see JavaScript build setup in the block editor handbook)?

    Because if you are, you wouldn’t need to manually specify the dependencies for your script, which is array( 'wp-blocks', 'wp-i18n', 'wp-element', 'wp-block-editor' ) in the question.

    However, you will need to use the import statement and not const when loading the dependencies in your script. So for example:

    // Instead of using "const":
    const { InnerBlocks, useBlockProps } = wp.blockEditor;
    
    // Use "import":
    import { InnerBlocks, useBlockProps } from '@wordpress/block-editor';
    

In response to your comment…

if I replace array( 'wp-blocks', 'wp-i18n', 'wp-element', 'wp-block-editor' ) with just array() or any other combination,
excluding any of them or all of them, I still get an error

The following excerpt might help:

Here is how to use this asset file to automatically set the dependency
list for enqueuing the script. This prevents having to manually update
the dependencies, it will be created based on the package imports
used within your block.

$asset_file = include( plugin_dir_path( __FILE__ ) . 'build/index.asset.php');

wp_register_script(
  'myguten-block',
  plugins_url( 'build/index.js', __FILE__ ),
  $asset_file['dependencies'],
  $asset_file['version']
);