3

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.

7
  • Why are you using a custom endpoint? What is its purpose? There's a lot of missing context here, and that's confusing. Why not just request the custom post types via their endpoint? I'm assuming you have show_in_rest set to true when the post type is registered. Please update your question so that the needed context is added. You've arrived at this point but it's not clear what you were trying to do and why it needed this
    – Tom J Nowell
    Commented Jan 6, 2021 at 15:39
  • reading Matt Watsons blog post, keep in mind he's trying to retrieve data that is not in the REST API, aka user roles. You don't need all those work arounds for custom post types
    – Tom J Nowell
    Commented Jan 6, 2021 at 15:41
  • Hey @TomJNowell , Thanks for the interest! As I already mentioned in the post, the reason for using a custom endpoint ins that getEntityRecords(the method that WordPress uses to retrieve posts on their Latest Post block) takes a really long time to execute and retrieve the info when there's a high volume of posts. So the goal with my custom endpoint is to optimize post data requests .
    – Camilo
    Commented Jan 6, 2021 at 17:21
  • I don't believe that makes things faster, as it's still querying the same posts from the same table. A CPT will have its own endpoint. This custom endpoint is unnecessary, and just adds technical debt and complexity. This is not good practice, and is not how it's supposed to work. You should be using the standard endpoint, if the endpoint is slow, it isn't because endpoints are inherently slow, it's because something is making it slow, a new endpoint that does the same thing doesn't fix that.
    – Tom J Nowell
    Commented Jan 6, 2021 at 20:42
  • 1
    I think we've drifted away of the issue I wanted to address with my question. To close out the endpoint discussion, just consider that I need a custom endpoint 'cause I need to do custom queries to the DB that I wouldn't be able to do with the existing endpoints. So going back to the initial issue here, Do you have any advice relating where or how should the dispatch('core').addEntities be used?
    – Camilo
    Commented Jan 8, 2021 at 16:36

1 Answer 1

1

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' }), []);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.