Gutenberg is not intended to do dynamic React stuff in front-end.
Nevertheless there is a way to bypass this problem:
I assume the structure of gutenberg block when using npm init @wordpress/block my-block
to init your block.
You have to register your own client-side script in my-block.php
to be executed on front-end; one drawback: it is loaded on every page.
function create_block_my_block_init()
{
$client_js = 'build/client.js';
wp_register_script(
'create-block-my-block-client',
plugins_url($client_js, __FILE__),
$script_asset['dependencies'],
$script_asset['version']
);
$client_css = 'build/client.css';
wp_register_style(
'create-block-my-block-client',
plugins_url($client_css, __FILE__),
array(),
filemtime("$dir/$client_css")
);
...
register_block_type('create-block/my-block', array(
...
'script' => 'create-block-my-block-client',
'style' => 'create-block-my-block-client', // Override default and import custom scss file.
));
}
Note that you can't use build/style-index.css
/ style.scss
anymore or use register_block_style
for that purpose. But better import your custom style via import './custom.scss';
in your React component (here: MyComponent
).
Add webpack.config.js
to your root folder in order to load your script:
const defaultConfig = require( '@wordpress/scripts/config/webpack.config' );
module.exports = {
...defaultConfig,
entry: {
...defaultConfig.entry,
client: './src/client.js',
},
};
Add a HTML wrapper for your front-end in the src/save.js
so you can reference your script:
export default function save() { return (
<div className="my-block-wrapper"></div>
);}
Note that you shouldn't add the wrapper to the src/edit.js
as the React components are loaded dynamically, so use directly your custom components there.
import MyComponent from '@path_to_node_modules/MyComponent';
export default function Edit( { className } ) { return (
<MyComponent/>
);}
Add your front-end react code to src/client.js
:
import { render } from '@wordpress/element';
import MyComponent from '@path_to_node_modules/MyComponent';
window.addEventListener('DOMContentLoaded', (event) => {
const wrappers = document.getElementsByClassName(`my-block-wrapper`);
for(let wrapper of wrappers) {
render(<MyComponent/>, wrapper);
}
});
See my full example here.
Source 1: https://javascriptforwp.com/adding-react-to-a-wordpress-theme-tutorial/
Source 2: https://stackoverflow.com/questions/51771125/wordpress-gutenberg-react-components-on-front-end
Source 3: https://www.youtube.com/watch?v=jauZCeLrGFA
If you have feedback or improvements feel free to edit.