3

As the title says, I just need to get user meta by the user ID in a custom Gutenberg block (editor side). Essentially what this would return in PHP: get_user_meta( $user_id, 'meta_key', true ); is the data that I need.

wp.data.select('core').getUserMeta(userId,'meta_key',true); doesn't seem to work, but it was a total guess as I can't seem to find any documentation about it. Does anyone know how I can do this?

2 Answers 2

3

With thanks to @Lovor's investigative answer, here's the approach that worked for me.

1. Add meta to REST as JSON:

In the plugin or theme functions, get the meta, maybe_unserialize it, json_encode it, and add it to the REST API:

function add_custom_meta_to_rest( $data, $user, $context ) {

    // Add some check here to set a default value if the key does not exist.
    $usermeta = get_user_meta( $user->ID, 'meta_key', true );

    $data->data['meta']['meta_key'] = json_encode( maybe_unserialize( $usermeta ) );

    return $data;
}
add_filter( 'rest_prepare_user', 'add_custom_meta_to_rest', 10, 3 );

2. Get the data in your block

In your block JS file, import useSelect and from there you can get the data inside your edit function:

// Import `useSelect`.
import { useSelect } from '@wordpress/data';

// Get users.
const users = useSelect(select => select('core').getUsers());

// Get user meta from `users` and parse the JSON.
// Be sure the user ID is set first, in this case as an attribute.
// Also be sure to replace the meta key.
var userMeta = users && users.length > 0 && users.find((user) => user.id === attributes.userId).meta.meta_key;
userMeta = JSON.parse(userMeta);

Test it to be sure: console.log(userMeta)

3. FYI...

If you want, you can also get the current user:

const currentUser = useSelect(select => select('core').getCurrentUser());

And then set userId as the current user's ID if it isn't set:

// You'll have import `useEffect` for this:
import { useEffect } from '@wordpress/element';

// Set userId to the current user id if it is not set.
useEffect(() => {
    if (!attributes.userId) {
        setAttributes({ userId: currentUser.id });
    }
}, []);

In my case, I needed all users anyway, but you can also get a single value by user ID, as @Lovor described:

const userName = useSelect(select => select('core').getUser(1,{'_fields':'name'}));
console.log(userName);

Note that if the metadata was an associative PHP array it'll be parsed as a Javascript object. If you want, you could convert it to an array of objects to more easily loop through and use the keys as values:

if (userMeta && typeof userMeta === 'object') {
    userMeta = Object.keys(userMeta).map((key) => {
        return { ...userMeta[key], id: key };
    });
}

Hope this helps someone.

2
  • Do you know if you can get the user id of the author of the current post (in the client)?
    – Kropotkin
    Commented Jul 17, 2023 at 9:09
  • However - your solution works well for me, thank you.
    – Kropotkin
    Commented Jul 17, 2023 at 9:30
2

Unfortunately, this is not documented at all. It took a while for me to get the answer by inspecting the code, and it is:

in browser console you can test at first:

wp.data.select('core').getUser(1,{context:'view'}) 

where 1 is ID of the user. You can also omit context, to get all meta data available from REST, or give context: 'edit'.

This gives you pretty detailed object as "answer" whose properties are metadata. If you need just certain fields, you can specify this (read REST manual, Global parameters):

wp.data.select('core').getUser(1,{'_fields':'first_name,last_name'}) 

From this, it is easy to refactor this to familiar form used in blocks:

import { useSelect } from '@wordpress/data';

function Edit() {
const USER_ID = 1;
const user_email = useSelect(select => select('core').getUser(USER_ID, '_fields': 'email'));

//some other code
}

When trying to find solution to such questions, you can always use getEntityRecord, all others such selectors are just shortcuts to this general selector. You should inspect WP REST API Handbook and you will find your answer. Here is link to users section

When you try to find or understand some more specific but undocumented selector, you should look in Gutenberg's core-data package, selectors.ts or entities.js which dynamically injects selectors. getUser selector is constructed from member of array rootEntitiesConfig line 104 in the code (name: user) and it gets get prefix in function getMethodName later in code.

5
  • Amazing, thanks, I wish the documentation on all this would get completed! I'm not sure if it matters but I've switched my implementation from getEntityRecords to getUsers and it works, so thanks for that. I'm working with custom meta which I still had to add to REST and all that, but this definitely helped.
    – Shoelaced
    Commented Jan 23, 2023 at 11:56
  • I wonder how you would get the user id of the current post? - FI - the above line wp.data.select('core').getUser(1,{'_fields':'first_name,last_name'}) errors for me. (No file entities.js in my install of WordPress 6.2.2)
    – Kropotkin
    Commented Jul 17, 2023 at 9:01
  • If there is REST endpoint which gives ID for author of current post, you can get it, at least by using getEntityRecords or some more specialized selector. If such endpoint does not exist already, you should create it.
    – Lovor
    Commented Jul 18, 2023 at 9:35
  • Also @Kropotkin, getCurrentUser() might be selector you need, it is the user who is currently editing post, and that user will be saved as author upon saving of the post.
    – Lovor
    Commented Jul 18, 2023 at 9:40
  • And entities.js is not in WordPress instalation, because you have compiled Gutenberg code. You should look instead in Gutenberg repository on github.
    – Lovor
    Commented Jul 18, 2023 at 9:42

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.