admin管理员组文章数量:1291224
In a plugin I'm developing, I registered a custom REST API route to get some post data passing a post id:
function rest_api_init() {
register_rest_route( 'custombase/v1', '/post/(?P<id>[\d]+)', array(
'methods' => 'GET',
'callback' => 'get_post_rest',
'permission_callback' => '__return_true',
'args' => array(
'id' => array(
'validate_callback' => function( $param, $request, $key ) {
return is_numeric( $param );
}
),
),
) );
}
function get_post_rest( WP_REST_Request $request ) {
$post = get_post( $request['id'] );
if ( is_wp_error( $post ) ) {
return $post;
}
$data = array(
'ID' => $post->ID,
'title' => $post->post_title,
);
$response = new WP_REST_Response( $data, 200 );
return $response;
}
I checked and the route is registered correctly as I can get info visiting, for example, the following URL:
This is the result:
{"ID":1239,"title":"My example post title"}
As I understand, I need to use the apiFetch
utility to make REST API requests to custom routes in Gutenberg. This is what I'm doing:
const mypost = apiFetch( { path: 'custombase/v1/post/1239' } ).then( ( post ) => {
return post;
} );
But, instead of post object, I'm getting a Promise
with the post object inside when I do a console.log( mypost )
:
Promise { <state>: "pending" }
<state>: "fulfilled"
<value>: Array [ {…} ]
0: Object { ID: 1239, title: "My example post title" }
length: 1
<prototype>: Array []
How can I get the post object instead?
In a plugin I'm developing, I registered a custom REST API route to get some post data passing a post id:
function rest_api_init() {
register_rest_route( 'custombase/v1', '/post/(?P<id>[\d]+)', array(
'methods' => 'GET',
'callback' => 'get_post_rest',
'permission_callback' => '__return_true',
'args' => array(
'id' => array(
'validate_callback' => function( $param, $request, $key ) {
return is_numeric( $param );
}
),
),
) );
}
function get_post_rest( WP_REST_Request $request ) {
$post = get_post( $request['id'] );
if ( is_wp_error( $post ) ) {
return $post;
}
$data = array(
'ID' => $post->ID,
'title' => $post->post_title,
);
$response = new WP_REST_Response( $data, 200 );
return $response;
}
I checked and the route is registered correctly as I can get info visiting, for example, the following URL:
https://example/wp-json/custombase/v1/post/1239
This is the result:
{"ID":1239,"title":"My example post title"}
As I understand, I need to use the apiFetch
utility to make REST API requests to custom routes in Gutenberg. This is what I'm doing:
const mypost = apiFetch( { path: 'custombase/v1/post/1239' } ).then( ( post ) => {
return post;
} );
But, instead of post object, I'm getting a Promise
with the post object inside when I do a console.log( mypost )
:
Promise { <state>: "pending" }
<state>: "fulfilled"
<value>: Array [ {…} ]
0: Object { ID: 1239, title: "My example post title" }
length: 1
<prototype>: Array []
How can I get the post object instead?
Share Improve this question edited May 28, 2021 at 21:10 leemon asked May 28, 2021 at 11:53 leemonleemon 2,0324 gold badges23 silver badges51 bronze badges 6 | Show 1 more comment1 Answer
Reset to default 6I'm getting a
Promise
with the post object inside when I do aconsole.log( mypost )
Yes, because apiFetch()
indeed returns a Promise
object, and apiFetch()
doesn't assign the response received from the server to the mypost
constant, and the return value of your then()
callback is also not going to be assigned to the mypost
variable.
How can I get the post object instead?
As suggested by React, you would want to add mypost
as a local state in your component, then make your XHR/AJAX request (using apiFetch()
, the native window.fetch()
, Axios or whatever) in the componentDidMount()
method of a class component, or use the useEffect
hook in a function component.
Example using apiFetch()
with useEffect
:
import { useState, useEffect } from '@wordpress/element';
import apiFetch from '@wordpress/api-fetch';
function MyComponent( { post_id } ) {
const [ error, setError ] = useState( null );
const [ mypost, setPost ] = useState( null );
const [ isLoaded, setIsLoaded ] = useState( false );
useEffect( () => {
apiFetch( { path: `custombase/v1/post/${ post_id }` } ).then(
( result ) => {
setIsLoaded( true );
setPost( result );
},
( error ) => {
setIsLoaded( true );
setError( error );
}
);
}, [ post_id ] );
if ( error ) {
return <p>ERROR: { error.message }</p>;
} else if ( ! isLoaded ) {
return <p>Loading post { post_id }..</p>;
} else if ( mypost && mypost.id ) {
return <h3>Post <i>{ mypost.title || '#' + mypost.id }</i> loaded!</h3>;
}
return <p>No such post</p>;
}
// Sample usage: <MyComponent post_id="1239" />
Alternate Solution: Add an entity for your custom endpoint into the list of entities in the block editor.
Add the entity using
addEntities()
:import { dispatch } from '@wordpress/data'; dispatch( 'core' ).addEntities( [{ baseURL: '/custombase/v1/post', // The 'post' is not a post type - it's the "post" as in /post above. Also, "kind" // and "name" are not documented, so let's assume they form the above baseURL.. kind: 'custombase/v1', name: 'post', label: 'Post or whatever', }] ); // You can, for example, call the above (i.e. add the entity) before you register your // block type.
Then use
getEntityRecord()
to fetch post data from the endpoint:const mypost = select( 'core' ).getEntityRecord( 'custombase/v1', 'post', 1239 ); // Note that getEntityRecord() caches the results.
And note that for
getEntityRecord()
to work correctly, your endpoint callback must use the lowercaseid
and notID
:// In the get_post_rest() function: $data = array( 'id' => $post->ID, // use id and *not* ID 'title' => $post->post_title, );
So for example using useSelect
, the above component (MyComponent
) could now look like so:
import { useSelect } from '@wordpress/data';
function MyComponent( { post_id } ) {
const { mypost, isLoading } = useSelect( ( select ) => {
const args = [ 'custombase/v1', 'post', post_id ];
return {
mypost: select( 'core' ).getEntityRecord( ...args ),
isLoading: select( 'core/data' ).isResolving( 'core', 'getEntityRecord', args )
};
}, [ post_id ] );
if ( isLoading ) {
return <p>Loading post { post_id }..</p>;
} else if ( mypost && mypost.id ) {
return <h3>Post <i>{ mypost.title || '#' + mypost.id }</i> loaded!</h3>;
}
return <p>No such post</p>;
}
本文标签: javascriptUsing apiFetch for retrieving post data in Gutenberg
版权声明:本文标题:javascript - Using apiFetch for retrieving post data in Gutenberg 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741531221a2383766.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
get_post
is called, and even if it was faster, it would still be slower than just bundling the data via the post endpoint and having it pre-added by the block editor so no additional requests are needed – Tom J Nowell ♦ Commented May 28, 2021 at 13:13