Gutenberg Block: Objects are not valid as a React child (found: [object HTMLDivElement])

Instead of using raw DOM nodes, use the WP Element wrapper components and build it with wp scripts

For example here is an ESNext block using modern JS:

    edit() {
        return (
            <div style={ blockStyle }>
                Hello World, step 1 (from the editor).
            </div>
        );
    },

And again using raw JS without the build step:

( function( blocks, i18n, element ) {
    var el = element.createElement;
....
        edit: function() {
            return el(
                'p',
                { style: blockStyle },
                'Hello World, step 1 (from the editor).'
            );
        },
...
} )( window.wp.blocks, window.wp.i18n, window.wp.element );

Here’s what your edit function might look like using modern JS:

    edit: function( props ) {
        const data = wp.data.select( 'core/block-editor' );
        const blocks = data.getBlocks();
        setHeadingAnchors(blocks);
        const headings = blocks.map( ( item, index ) => {
            if ( item.name === 'core/heading' ) {
                return null;
            }
            return <li>{item.attributes.content}</li>;
        } );
        return <div>
            <h2>{ __( 'Table of Contents', 'simpletoc' ) }</h2>
            <ul>
                {headings}
            </ul>
        </div>;
    },

Then we can use wp scripts to build it:

https://github.com/WordPress/gutenberg-examples/blob/master/01-basic-esnext/package.json#L19-L22

As a result it will build the script and handle all the JSX and make sure it uses the WordPress element wrapper ( otherwise you’d have to use el( 'p' etc. It’ll even give you a PHP file that returns an array of JS dependencies for wp_enqueue_script so that your built JS stays super lean, and gets loaded at the correct time in the editor

Sidenotes:

  • item['name'] will give you issues, item is an object, not an array
  • indent! Indent correctly and consistently
  • It looks like you have a funciton setHeadingAnchors that meddles in the affairs of other blocks, I’d advise against this
  • You should use this code in your save function as well, the only thing your PHP needs to do is enqueue the JS, and ensure any assets needed on the frontend are loaded