How to get data from WordPress $wpdb into React Gutenberg Blocks Frontend?

Actually, there are many ways to do what you asked, but I’m going to give you an example based on this example on the official React website, which uses AJAX with a class-based component (but there’s also an example there using function component with hooks).

So for the PHP part, we’ll create a custom REST API endpoint and just for testing purposes, we’re simply going to return an array with two items, each having three properties: id, name and price.

As for the AJAX part, we’ll use the apiFetch() in the @wordpress/api-fetch package to fetch data from the custom endpoint — you could just use the native fetch() function in JavaScript, but with apiFetch(), it makes it easy if your endpoint requires/needs authentication because you don’t need to worry about the cookie nonce since it’s already included by apiFetch().

The Code

  • PHP — Register the custom REST API endpoint:

    add_action( 'rest_api_init', 'my_rest_api_init', 10, 1 );
    function my_rest_api_init() {
        register_rest_route( 'my-plugin/v1', '/items', array(
            'methods'             => 'GET',
            'permission_callback' => '__return_true', // *always set a permission callback
            'callback'            => function ( $request ) {
                return array(
                    array( 'id' => 1, 'name' => 'Apples', 'price' => '$2' ),
    
                    // I used is_user_logged_in() so you can see that apiFetch() by default
                    // sends the cookie nonce when making an API request.
                    array( 'id' => 2, 'name' => 'Peaches', // wrapped
                        'price' => is_user_logged_in() ? 'FREE :)' : '$5' ),
                );
            },
        ) );
    }
    
  • JS and AJAX — The PruefungenEdit component:

    // don't forget to import the apiFetch()
    import apiFetch from '@wordpress/api-fetch';
    
    class PruefungenEdit extends Component {
        constructor( props ) {
            super( props );
            this.state = {
                error: null,
                isLoaded: false,
                items: [],
            };
        }
    
        componentDidMount() {
            apiFetch( { path: 'my-plugin/v1/items' } )
                .then(
                    ( items ) => {
                        this.setState( {
                            isLoaded: true,
                            items,
                        } );
                    },
                    // Note: It's important to handle errors here instead of a catch() block
                    // so that we don't swallow exceptions from actual bugs in components.
                    ( error ) => {
                        this.setState( {
                            isLoaded: true,
                            error,
                        } );
                    }
            );
        }
    
        render() {
            const { error, isLoaded, items } = this.state;
    
            // If there's an error in fetching the remote data, display the error.
            if ( error ) {
                return <div>Error: { error.message }</div>;
            // If the data is still being loaded, show a loading message/icon/etc.
            } else if ( ! isLoaded ) {
                return <div>Loading...</div>;
            // Data loaded successfully; so let's show it.
            } else {
                return (
                    <ul>
                    { items.map( item => (
                        <li key={ item.id }>
                            { item.name } <i>{ item.price }</i>
                        </li>
                    ) ) }
                    </ul>
                );
            }
        }
    }
    

So I hope that helps and just let me know if you need any clarification. However, do take your time to review the first, third and fourth links above. 🙂

Leave a Comment