I’m working on a block that, like many, isn’t limited to a single instance in the editor (and thus not the frontend); however, because there are certain features of the block I want to manipulate when the page loads, I want generate a reference to said block.
For example, the structure of the markup in the edit
function looks something like this:
<div className="wp-acme-block"> <div className="wp-acme-block-editor"> </div> <div className="wp-acme-block-preview"> </div>
</div>
The functionality will allow the user to toggle the visibility of the editor
container and the preview
container. And to manage this functionality, I want to access the parent element of each one. Specifically, the one with the class wp-acme-block
.
And this is easy to do with a couple of features of React:
useRef
is a hook that allows for direct interaction with the DOM. It returns aref
object that maintains a property calledcurrent
. This enables us to maintain a reference to a specific element.useEffect
is a hook that handles side effects in functional components. It allows us to do a lot of things (like fetching data) but also allows us to manually work with the DOM.
Given those two hooks, I can place a ref
attribute on the primary container that I can then use elsewhere in the code.
First, in the header of the file add the following:
import { useRef, useEffect } from 'react';
Then at the top of the edit
function, I have the following code:
edit: ({ attributes, setAttributes }) => { const blockRef = useRef(null); // ...
};
Then, in the edit
function where I have the markup that I’ve shown above, I’ll add the ref
attribute:
<div className="wp-acme-block" ref={blockRef}> <div className="wp-acme-block-editor"> </div> <div className="wp-acme-block-preview"> </div>
</div>
And finally, I can use this reference in the edit
function before it calls return
so I can refer to the element in other functions.
useEffect(() => { acmePreviewFunction(blockRef.current);
}, []);
So the full, relevant code looks like this:
import { useRef, useEffect } from 'react'; // ... registerBlockType('acme/example-block', { // ... attributes: { // ... }, edit: ({ attributes, setAttributes }) => { const blockRef = useRef(null); // ... useEffect(() => { acmePreviewFunction(blockRef.current); }, []); // ... return ( <div className="wp-acme-block" ref={blockRef}> <div className="wp-acme-block-editor"> </div> <div className="wp-acme-block-preview"> </div> </div> ); }, // ...
});
Then passing the current
property as an argument to other functions, you’ve got access to the block such that you can manipulate it with other JavaScript functions.
Further, the ref
will refer only to the instance of the block so it won’t manipulate other instances of the block located in the editor (or, more specifically, the DOM).