Gutenberg Tips — Generate your block’s class name using useBlockProps()
useBlockProps
has been introduced since WordPress 5.6, which fixes a previous weird issue where the className
property is only passed in the edit function but not the save function in registerBlockType
. With useBlockProps
, we can use the same ‘wp-block-’ prefixed class name in both the edit and save functions!
Assuming your registered block type has the name: ‘myfirstblock/gtg-demo
’, then the default generated className we can extract from useBlockProps
would be ‘wp-block-myfirstblock-gtg-demo
’(forward slashes are converted to hyphens).
Prerequisites of using useBlockProps
Firstly, make sure your WordPress version is 5.6 or above.
Secondly, pass key/value pair (‘api_version’ => 2) to the register_block_type
arguments array like this:
register_block_type( 'myfirstblock/gtg-demo', array(
'api_version' => 2,
'editor_script' => 'gtg-demo-editor-script',
'editor_style' => 'gtg-demo-editor-style',
'style' => 'gtg-demo-style'
) );
Thirdly, import useBlockTypes
from wp.blockEditor
at the top of your editor script:
const { useBlockProps } = wp.blockEditor;
Lastly, set apiVersion as 2 also in registerBlockType
in your editor script:
registerBlockType( 'myfirstblock/gtg-demo', {
apiVersion: 2,
...
Usage of useBlockProps
The Official block tutorial has also been updated to demonstrate with this React hook. The most verbose explanation I can find on WordPress docs on how to use useBlockProps
is at here. Quoting from the docs:
…but in order for the Gutenberg editor to know how to manipulate the block, add any extra classNames that are needed for the block… the block wrapper element should apply props retrieved from the
useBlockProps
react hook call. The block wrapper element should be a native DOM element, like<div>
and<table>
, or a React component that forwards any additional props to native DOM elements. Using a<Fragment>
or<ServerSideRender>
component, for instance, would be invalid.If the element wrapper needs any extra custom HTML attributes, these need to be passed as an argument to the
useBlockProps
hook.
See the below code example which shows how the React hook can be used; I’m importing the hook from the global wp variable:
const { registerBlockType } = wp.blocks;
const { useBlockProps } = wp.blockEditor;
import './editor.scss';registerBlockType( 'myfirstblock/gtg-demo', {
apiVersion: 2,
title: 'GTG Demo Block',
icon: 'heading', // https://developer.wordpress.org/resource/dashicons/#heading
category: 'text',
edit: props => {
const blockProps = useBlockProps( {
className: 'gtg-demo-h1',
'data-id': 'special-h1-id'
} );
return (
<h1 {...blockProps}>Hello World!</h1>
);
},
save: props => {
const blockProps = useBlockProps.save( {
className: 'gtg-demo-h1',
} );
return (
<h1 {...blockProps}>Hello World!</h1>
);
},
} );
My rendered h1 element in the Block Editor
Notice that we have both the generated ‘wp-block-myfirstblock-gtg-demo
’ and the custom ‘gtg-demo-h1
’ class names. Also our custom ‘data-id
’ attribute is included too:
<h1 class="wp-block-myfirstblock-gtg-demo block-editor-block-list__block wp-block is-selected gtg-demo-h1" data-id="special-h1-id" id="block-f0ac2755-01e3-4e3b-9356-4af9ee46fb0d" tabindex="0" role="group" aria-label="Block: GTG Demo Block" data-block="f0ac2755-01e3-4e3b-9356-4af9ee46fb0d" data-type="myfirstblock/gtg-demo" data-title="GTG Demo Block">Hello World!</h1>
My rendered h1 element in the frontend
<h1 class="wp-block-myfirstblock-gtg-demo gtg-demo-h1">Hello World!</h1>