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
useStateto 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
useEffectto make the AJAX calls and then update the above states. And note thatuseEffectruns 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
keyin 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