Gurenberg Block: How to migrate from el-Functions to JSX elements?

I tried to add the toolbar component and I get a syntax error about my
brackets

First off, JSX is indeed easier and it works like regular HTML, but with the ability to use JavaScript expressions (string literals, variables, function calls, etc.), e.g. <p>Hello, { name }</p> or <p>{ Date.now() }</p>.

Now the thing which caused that syntax error is this part:

className={components-icon-button components-toolbar__control}

Because anything inside the brackets ({ this part }) is a regular JavaScript expression, so if you’re outputting a static string, then it has to be enclosed in single/double quotes:

// Bad
className={components-icon-button components-toolbar__control}

// Good
className={'components-icon-button components-toolbar__control'}

But actually, for static attribute values, you could simply do <attribute>="<value>": className="components-icon-button components-toolbar__control", i.e. no need to use the { expression } format. 🙂

// Static attribute value.
const MyDiv = <div className="foo bar">baz</div>;

// Dynamic attribute value.
const someClass = someFunction() ? 'yes' : 'no';
const MyDiv2 = <div className={ 'foo bar ' + someClass }>baz</div>;

// Same as above, but without using the someClass variable.
const MyDiv3 = <div className={ 'foo bar ' + ( someFunction() ? 'yes' : 'no' ) }>baz</div>;

Adjacent JSX elements must be wrapped in an enclosing tag

That’s a generic React error which occurs when a (React) component returns two or more adjacent elements instead of one:

  • This will result in the above error because unless you return an array of elements (see bullet #3 below), React expects a component to return just a single element:

    // This is equivalent to "return 1 2", "const a = (1 2)" or "const a = 1 2" which
    // results in a syntax error :(
    const MyComponent = (
        <div>foo bar</div>
        <p>baz boo</p>
    );
    
  • But that one single element can contain as many elements as you want. And if that’s the case, use a parent element (div, p, a custom component, etc.) or a (React) fragment — which is exported as wp.element.Fragment in the global window object on the WordPress editor pages:

    // Using Fragment (the short syntax, i.e. <> with </>).
    const MyComponent = (
        <>
            <div>foo bar</div>
            <p>baz boo</p>
        </>
    );
    
    // Using div as the parent element.
    const MyComponent = (
        <div>
            <div>foo bar</div>
            <p>baz boo</p>
        </div>
    );
    
  • Or as mentioned above (bullet #1), you can return an array containing the top-level adjacent elements, but a key should be set in each element:

    // The output/HTML will be the same as the one that uses the Fragment (<> and </>).
    const MyComponent = ([ // <- returns an array
        <div key="one">foo bar</div>,
        <p key="two">baz boo</p>
    ]);
    

So in your case, you’d probably want to use:

<>
    <BlockControls>
        ... your code.
    </BlockControls>
    <p>
        ... your code.
    </p>
</>

And you can find more insights on the “must be wrapped” error here, but the answers used React.xxx which should be wp.element.xxx in Gutenberg or the WordPress block editor.