Custom Gutenberg block: access dom element via JavaScript

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.

  1. 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( [] );
    
  2. Use useEffect to make the AJAX calls and then update the above states. And note that useEffect 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 );
                }
            );
    }, [] );
    
  3. 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

  1. The key in the above <tr> tag is a special property that should always be specified in a list. More details here.

  2. If you’re making a request to a custom WordPress REST API endpoint, you can use apiFetch() instead of fetch(). See my answer here for an example