Search code examples
wordpressgutenberg-blockscreate-guten-block

WordPress gutenberg custom block fails to render


I'm trying to rewrite a Short-Code to a Gutenberg block. I'm not experienced in React, though I've been coding Angular 2+ since 2017.

I created my block with the following command:

> npx @wordpress/create-block give-camp-blocks-plugin

I built and ran it. My block visually edits fine. I can use the browser inspect and it has the appropriate HTML. But, switching to 'code editor' and the all that is rendered is the following:

<!-- wp:create-block/give-camp-blocks-plugin /-->

And, I get the following error:

TypeError: object null is not iterable (cannot read property Symbol(Symbol.iterator))
    at Function.from (<anonymous>)
    at l (http://localhost:9139/wp-includes/js/dist/data.min.js?ver=90cebfec01d1a3f0368e:2:19718)
    at Object.__unstableMarkListeningStores (http://localhost:9139/wp-includes/js/dist/data.min.js?ver=90cebfec01d1a3f0368e:2:20176)
    at http://localhost:9139/wp-includes/js/dist/data.min.js?ver=90cebfec01d1a3f0368e:9:2223
    at p (http://localhost:9139/wp-includes/js/dist/data.min.js?ver=90cebfec01d1a3f0368e:9:2121)
    at http://localhost:9139/wp-includes/js/dist/data.min.js?ver=90cebfec01d1a3f0368e:9:2214
    at $e (http://localhost:9139/wp-includes/js/dist/data.min.js?ver=90cebfec01d1a3f0368e:9:2643)
    at Be (http://localhost:9139/wp-includes/js/dist/data.min.js?ver=90cebfec01d1a3f0368e:9:2964)
    at hs (http://localhost:9139/wp-includes/js/dist/editor.min.js?ver=f49ef02c2dddb31edd0e:19:124768)
    at kt (http://localhost:9139/wp-includes/js/dist/vendor/react-dom.min.js?ver=18.2.0:10:47633)

I stripped the implementation down to the bare minimum as follows:

const { __ } = wp.i18n;
import metadata from './block.json';
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps, RichText } from '@wordpress/block-editor';
//
registerBlockType( metadata.name, {
  apiVersion: metadata.apiVersion,
  title: metadata.title,
  //
  edit: ( { attributes, setAttributes } ) => {
    const { content } = attributes;
    const blockProps = useBlockProps( {
      className: "gc-marquee"
    } );
    blockProps['role'] = 'marquee';
    blockProps['aria-label'] = __(content);
    //
    return (
      <>
      <div
        { ...blockProps }
        >
        <RichText
          className="gc-scrollingtext"
          aria-hidden="true"
          tagName="p"
          placeholder={ 'Write text here ...' }
          value={ content }
          onChange={ ( value ) => setAttributes( { content: value } ) }
        />
      </div>
      </>
    );
  },
  save: ( { attributes } ) => {
    const { content } = attributes;
    const blockProps = useBlockProps.save( {
      className: "gc-marquee"
    } );
    blockProps['role'] = 'marquee';
    blockProps['aria-label'] = __(content);
    //
    return (
      <>
      <div
        { ...blockProps }
        >
        <RichText.Content
          className="gc-scrollingtext"
          aria-hidden="true"
          tagName="p"
          value={ content }
        />
      </div>
      </>
    );
  },
} );

The following is a snippet of block.json:

{
    ...
    "attributes": {
        "content":  {
            "type": "string",
            "source": "html",
            "selector": "p",
            "default": ""
        }
    },
    ...
}

When I click publish and refresh the page is corrupt and nothing displays. Not the title, not the sidebar, nothing displays. I'm at a lose of what I'm doing wrong.


Solution

  • I found the answers in the Gutenberg examples. So, this is what my bare minimum example now looks like:

    const { __ } = wp.i18n;
    import metadata from './block.json';
    import { registerBlockType } from '@wordpress/blocks';
    import { useBlockProps, RichText } from '@wordpress/block-editor';
    //
    registerBlockType( metadata.name, {
      apiVersion: metadata.apiVersion,
      title: metadata.title,
      //
      edit: ( props ) => {
        const {
          attributes: { content, padding },
          setAttributes,
        } = props;
        const blockProps = useBlockProps( {
          className: "gc-marquee"
        } );
        blockProps['role'] = 'marquee';
        blockProps['aria-label'] = __(content);
        //
        return (
          <div
            { ...blockProps }
            >
            <RichText
              className="gc-scrollingtext"
              aria-hidden="true"
              tagName="p"
              placeholder={ 'Write text here ...' }
              value={ content }
              onChange={ ( value ) => setAttributes( { content: value } ) }
            />
          </div>
        );
      },
      //
      // <!-- wp:give-camp/gc-test-sample -->
      // <div class="wp-block-give-camp-gc-test-sample gc-marquee" aria-label="ace" role="marquee">
      //  <p class="gc-scrollingtext" aria-hidden="true">ace</p>
      // </div>
      // <!-- /wp:give-camp/gc-test-sample -->
      //
      save: ( props ) => {
        const {
          attributes: { content }
        } = props;
        const blockProps = useBlockProps.save( {
          className: "gc-marquee"
        } );
        blockProps['role'] = 'marquee';
        blockProps['aria-label'] = __(content);
        //
        return (
          <div
            { ...blockProps }
            >
            <RichText.Content
              className="gc-scrollingtext"
              aria-hidden="true"
              tagName="p"
              value={ content }
            />
          </div>
        );
      },
    } );
    

    I removed the following:

    <>
    ...
    </>
    

    I changed the call to edit and save to use props, but I don't know if that really did anything...

    So, I got the bare minimum example to work, but the real code still didn't work. Back to the Gutenberg examples, I finally got the real code to work changing the edit function (I thought it would be in the save, but it wasn't).

    return (
      <div
        { ...blockProps }
        style={ {
          backgroundColor: bg_color, color: text_color, fontSize: font_size,
          padding: `${padding.top} ${padding.right} ${padding.bottom} ${padding.left}`
        } }
        >
        {
          <InspectorControls key="setting">
            <PanelBody
              ...
            </PanelBody>
          </InspectorControls>
        }
        <RichText
          className="gc-scrollingtext"
          style={ { margin: 0, } }
          aria-hidden="true"
          tagName="p"
          data-milli-sec={ milli_sec }
          value={ __(content) }
          placeholder={ placeholder }
          onChange={ ( value ) => setAttributes( { content: value } ) }
        />
      </div>
    );
    

    I had to place a class {} around the InspectorControls.

    Also, make sure in the save method, that one uses the save method for useBlockProps.save and the Content method for controls like RichText.Content and InnerBlocks.Content.

    Also, in the usage of wp.i18n __ method. The second parameter is the text domain, that is found in block.json. I get the value and use it in the method as follows:

    title={ __('Millisecond delay', textdomain ) }
    

    EsLint does not like textdomain, because it is a variable.