I have read many tutorial and no one is using the el() syntax but the "markup syntax" (JSX?). Here is my example:
This worked fine, but I think I have to migrate to make it easier readable:
edit: function(props) {
return [
el(
BlockControls, { key: 'controls' },
el( Toolbar, null,
el(
IconButton, {
className: 'components-icon-button components-toolbar__control',
label: __('Update table of contents', 'simpletoc'),
onClick: function() {
sendfakeAttribute(props)
},
icon: 'update'
}
)
)
),
el(
'p', { className: props.className },
el(
ServerSideRender, {
block: props.name,
attributes: props.attributes
}
)
)
];
I tried this and it works!
edit: function(props) {
return (
<p className={props.className}>
<ServerSideRender block={props.name} attributes={props.attributes} />
</p>
)
},
But then I tried to add the toolbar component and I get a syntax error about my brackets:
<BlockControls>
<Toolbar>
<IconButton
className={components-icon-button components-toolbar__control}
label={__('Update table of contents', 'simpletoc')}
onClick={function() {
sendfakeAttribute(props)
}}
icon={update}
/>
</Toolbar>
</BlockControls>
<p className={props.className}>
<ServerSideRender block={props.name} attributes={props.attributes} />
</p>
I think I don't understand how to escape the code correctly. Even if I leave out all the attributes of the icon-button I get this error:
Adjacent JSX elements must be wrapped in an enclosing tag
Any guidance on that? More examples would be great in the documentation.
I have read many tutorial and no one is using the el() syntax but the "markup syntax" (JSX?). Here is my example:
This worked fine, but I think I have to migrate to make it easier readable:
edit: function(props) {
return [
el(
BlockControls, { key: 'controls' },
el( Toolbar, null,
el(
IconButton, {
className: 'components-icon-button components-toolbar__control',
label: __('Update table of contents', 'simpletoc'),
onClick: function() {
sendfakeAttribute(props)
},
icon: 'update'
}
)
)
),
el(
'p', { className: props.className },
el(
ServerSideRender, {
block: props.name,
attributes: props.attributes
}
)
)
];
I tried this and it works!
edit: function(props) {
return (
<p className={props.className}>
<ServerSideRender block={props.name} attributes={props.attributes} />
</p>
)
},
But then I tried to add the toolbar component and I get a syntax error about my brackets:
<BlockControls>
<Toolbar>
<IconButton
className={components-icon-button components-toolbar__control}
label={__('Update table of contents', 'simpletoc')}
onClick={function() {
sendfakeAttribute(props)
}}
icon={update}
/>
</Toolbar>
</BlockControls>
<p className={props.className}>
<ServerSideRender block={props.name} attributes={props.attributes} />
</p>
I think I don't understand how to escape the code correctly. Even if I leave out all the attributes of the icon-button I get this error:
Adjacent JSX elements must be wrapped in an enclosing tag
Any guidance on that? More examples would be great in the documentation.
Share Improve this question asked Jan 6, 2021 at 11:20 MarcMarc 6979 silver badges28 bronze badges 1- 1 You can't return multiple things in a function unless you put them in an array, JSX is no different – Tom J Nowell ♦ Commented Jan 6, 2021 at 13:04
1 Answer
Reset to default 4I 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 aswp.element.Fragment
in the globalwindow
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.