admin管理员组

文章数量:1387323

I am trying to add some html from one of my functions the edit and save funktion. If I do it manually it works:

return <p>Hello World</p>;

But if I do it with a function that returns a dom element, I get this error:

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

But if I do a console.info chrome displays the html. Any idea why this does not work?

registerBlockType( 'simpletoc/toc', {
    title: __( 'SimpleTOC', 'simpletoc' ),
    icon: listul,
    category: 'layout',
    edit: function( props ) {
            const data = wp.data.select( 'core/block-editor' );
            const blocks = data.getBlocks();
            console.info(generateTOC(blocks));
      return generateTOC(blocks);
    },
    save: ( props ) => {
          return generateTOC(blocks);
    },
} );

function generateTOC(blocks){
    var div = document.createElement('div');
    var ul = document.createElement('ul');
    var h2 = document.createElement('h2');
    var headline = __( 'Table of Contents', 'simpletoc' );
  h2.appendChild(document.createTextNode(headline));

    blocks.forEach(function (item,index){
        var blockId = '';
        var slug = '';

        h2 = document.createTextNode(headline)
        var title = '';
        if ( item['name'] === 'core/heading' ) {
            blockId = (item['clientId']);
            title = item.attributes.content;
            slug = item.attributes.content.toSlug();
            var li = document.createElement('li');
            li.appendChild(document.createTextNode(title));
            ul.appendChild(li);
        }
    });

    div.appendChild(h2);
    div.appendChild(ul);

    return div;
}

I am trying to add some html from one of my functions the edit and save funktion. If I do it manually it works:

return <p>Hello World</p>;

But if I do it with a function that returns a dom element, I get this error:

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

But if I do a console.info chrome displays the html. Any idea why this does not work?

registerBlockType( 'simpletoc/toc', {
    title: __( 'SimpleTOC', 'simpletoc' ),
    icon: listul,
    category: 'layout',
    edit: function( props ) {
            const data = wp.data.select( 'core/block-editor' );
            const blocks = data.getBlocks();
            console.info(generateTOC(blocks));
      return generateTOC(blocks);
    },
    save: ( props ) => {
          return generateTOC(blocks);
    },
} );

function generateTOC(blocks){
    var div = document.createElement('div');
    var ul = document.createElement('ul');
    var h2 = document.createElement('h2');
    var headline = __( 'Table of Contents', 'simpletoc' );
  h2.appendChild(document.createTextNode(headline));

    blocks.forEach(function (item,index){
        var blockId = '';
        var slug = '';

        h2 = document.createTextNode(headline)
        var title = '';
        if ( item['name'] === 'core/heading' ) {
            blockId = (item['clientId']);
            title = item.attributes.content;
            slug = item.attributes.content.toSlug();
            var li = document.createElement('li');
            li.appendChild(document.createTextNode(title));
            ul.appendChild(li);
        }
    });

    div.appendChild(h2);
    div.appendChild(ul);

    return div;
}
Share Improve this question edited Apr 15, 2020 at 21:20 Marc asked Apr 15, 2020 at 20:28 MarcMarc 6979 silver badges28 bronze badges 4
  • Are you sure it's possible to return raw DOM nodes? WP provides a wrapper for components that should handle all of this, and it'll convert actual HTML tags into components if you use WP Scripts as well. What does setHeadingAnchors do? – Tom J Nowell Commented Apr 15, 2020 at 21:05
  • I removed setHeadingAnchors(). Has nothing to do with this problem. It sets anchors to all headings. Ok what is the wrapper then? How do I set HTML programmatically? – Marc Commented Apr 15, 2020 at 21:21
  • I'd recommend taking a look at this example: github/WordPress/gutenberg-examples/tree/master/… Mainly as it shows the preferred way to build the JS into the final product, and what a basic block is supposed to look like – Tom J Nowell Commented Apr 15, 2020 at 21:22
  • Here's the non-esnext JS version github/WordPress/gutenberg-examples/tree/master/01-basic – Tom J Nowell Commented Apr 15, 2020 at 21:22
Add a comment  | 

1 Answer 1

Reset to default 3

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/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

本文标签: pluginsGutenberg Block Objects are not valid as a React child (found object HTMLDivElement)