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. 🙂