I need to access the dom element inside the editor.
useRef
can be used for that, but actually, instead of doing that, I would just apply the approach shown below to my edit()
function 🙂
https://reactjs.org/docs/faq-ajax.html
So using a function component, you can achieve the same thing your front-end script does like so:
Remember to load useState
and useEffect
, e.g. add import { useState, useEffect } from '@wordpress/element';
at the top in your file.
-
Use
useState
to add states which will be used to determine whether we should display an error, a loading message or the items fetched from the remote API.const [ error, setError ] = useState( null ); const [ isLoaded, setIsLoaded ] = useState( false ); const [ items, setItems ] = useState( [] );
-
Use
useEffect
to make the AJAX calls and then update the above states. And note thatuseEffect
runs after the block is rendered in the editor (i.e. attached to the DOM).useEffect( () => { fetch( 'https://xxxxxxx?rows=50' ) .then( res => res.json() ) .then( result => { setIsLoaded( true ); // * Change this accordingly, e.g. if `result` is not an array // and instead an object with keys like 'items' or 'products'. setItems( result ); }, error => { setIsLoaded( false ); setError( error ); } ); }, [] );
-
Now display the fetched items, or a loading message, or an error:
return ( <div { ...useBlockProps() }> <table className="my-plugin-table"> <thead> <th>Key</th> <th>Label</th> </thead> <tbody> { error && ( <tr><td colspan="2">Error: { error.message }</td></tr> ) } { ! error && ! isLoaded && ( <tr><td colspan="2">Loading items..</td></tr> ) } { isLoaded && items.map( item => ( <tr key={ 'item-' + item.key }> <td>{ item.key }</td> <td>{ item.label }</td> </tr> ) ) } </tbody> </table> </div> );
Additional Notes
-
The
key
in the above<tr>
tag is a special property that should always be specified in a list. More details here. -
If you’re making a request to a custom WordPress REST API endpoint, you can use
apiFetch()
instead offetch()
. See my answer here for an example