So, I’ve created a custom endpoint to retrieve some post data I need to retrieve for a feature I’m building for some custom Gutenberg blocks. After reading this answer I started doing my own implementation of it. But I have my doubts regarding how, or when should I add my custom entity. So far I’ve been adding my custom entity with a custom hook in editor.BlockEdit
. Here’s how it looks:
import {addFilter} from '@wordpress/hooks';
import {dispatch, select} from '@wordpress/data';
addFilter('editor.BlockEdit', 'CustomGutenberg/customEntities', ((BlockEdit) => (props) => {
registerCustomEntities();
// (...)
return <BlockEdit {...props} />;
}));
const registerCustomEntities = () => {
const {getEntitiesByKind} = select('core');
const namespace="custom/v1";
if (getEntitiesByKind(namespace).length === 0) {
dispatch('core').addEntities([
{
label: 'Custom Posts',
name: 'posts',
kind: namespace,
baseURL: namespace + '/posts'
}
]);
}
}
And it works just fine, but the fact that I have to be checking if the entity has already been added in an if statement on top makes me think that I may not be using the right hook/filter/function to register my custom entity. And That’s why I would like to get some more input, as the addEntities
function is not properly documentated as far as I’m concerned.
Further context: Why do I need a custom endpoint to begin with?
I’ve been developing Gutenberg blocks for a while and sometimes I’ve ran into a requirement where I need a list of all the existing posts of a given CPT. So I use getEntityRecords to get that list, but usually I only need each post ID and raw title. But then I run into an issue with getEntityRecords, since it requests -and retrieves- all of the post’s attributes, making the request take a really long time when there’s a high volume of posts.
1 Answer
I stumbled upon this question long after it was asked – but for the sake of all readers in search on how to use this indeed poorly documented function, here is my answer:
Do not use addEntities in the filter. It is not the same logic as in PHP backend. Putting it into BlockEdit
filter indeed creates problem of calling it when registering each block, and hence you have to use this workaround which you did put in your code.
Call it simply in the main script which is registered with block (usually index.js) or you can call it in edit.js (if your block has separate file for edit). What is important is to call it outside of Edit function, or any WordPress React element, since that will cause the same problems as you experienced, because it is called too late and/or repeatably.
Additionaly, if you look at the definition of getEntityRecords, you will observe that it has fourth parameter (actually third, since you don’t provide state when calling it) query
, which you can use to obtain only fields that you need, without the need to build custom REST endpoints.
In global REST parameters of WordPress, there is a _fields parameter which you should use as property of object in that call, like so (this is a call inside Edit function):
const postTitlesList = useSelect(select => select('core').getEntityRecords('postType', 'post', { ['_fields']: 'id,title' }), []);