I have this working in my plugin and all is well with the world:

edit: withAPIData( props => {
            return {
                roles: '/matt-watson/secure-blocks/v1/user-roles/'
            };
        } )( props => {

....

However guidance here suggests that this will no longer be supported going forward: https://github.com/WordPress/gutenberg/issues/7390#issuecomment-398667802

So I have managed to work that into the solution:

const DEFAULT_STATE = {
userRoles: {},
};

const actions = {
    setUserRoles( userRoles ) {
        return {
            type: 'SET_USER_ROLES',
            userRoles,
        };
    },

    fetchFromAPI( path ) {
        return {
            type: 'FETCH_FROM_API',
            path,
        };
    },
};

registerStore( 'matt-watson/secure-block', {
    reducer( state = DEFAULT_STATE, action ) {

        switch ( action.type ) {
            case 'SET_USER_ROLES':
                return {
                    ...state,
                    userRoles: action.userRoles,
                };
        }

        return state;
    },

    actions,

    selectors: {
        getUserRoles( state ) {
            const { userRoles } = state;
            return userRoles;
        },
    },

    controls: {
        FETCH_FROM_API( action ) {
            return apiFetch( { path: action.path } );
        },
    },

    resolvers: {
        * getUserRoles( state ) {
            const path = '/matt-watson/secure-blocks/v1/user-roles/';
            const userRoles = yield actions.fetchFromAPI( path );
            return actions.setUserRoles( userRoles );
        },
    }

    ,
    } );

....

edit: withSelect( ( select ) => {
                                return {
                                    roles: select('matt-watson/secure-block').getUserRoles(),
                                };
                            } )( props => {

....

Now the issue is that the 'controls' section never fires. In the documentation it says that this is an opt-in component, and I need to enable it via the use command: https://github.com/WordPress/gutenberg/tree/master/packages/data#controls

When I try this, use is undefined.

So my question is this. As withAPIData did everything I needed in a very quick and easy way, is there an alternative 'drop-in' bit of code I can use, or do I need to progress with the store that I am registering? If so, what am I doing wrong?

Any help appreciated. Thank you.

  • I would note that ... is also valid javascript, as the object spread operator – Tom J Nowell Aug 14 at 15:45
  • I would also guess that you need to define some packages as requirements via npm for the parts that require use – Tom J Nowell Aug 14 at 15:51
  • Thanks @TomJNowell, yeah good point on the ... I'll have to come up with another way to add snippets. I'll have another look into use. If I fix this I'll write a glorious blog post! – Matt Watson Aug 14 at 18:29
  • Hmm, no luck importing @wordpress/data, I can get the use functions, but not a lot happens. – Matt Watson Aug 14 at 19:59

I've cracked it!

const actions = {
    setUserRoles( userRoles ) {
        return {
            type: 'SET_USER_ROLES',
            userRoles,
        };
    },

    receiveUserRoles( path ) {
        return {
            type: 'RECEIVE_USER_ROLES',
            path,
        };
    },
};

const store = registerStore( 'matt-watson/secure-block', {
    reducer( state = { userRoles: {} }, action ) {

        switch ( action.type ) {
            case 'SET_USER_ROLES':
                return {
                    ...state,
                    userRoles: action.userRoles,
                };
            case 'RECEIVE_USER_ROLES':
                return action.userRoles;
        }

        return state;
    },

    actions,

    selectors: {
        receiveUserRoles( state ) {
            const { userRoles } = state;
            return userRoles;
        },
    },

    resolvers: {
        * receiveUserRoles( state ) {
            const userRoles = apiFetch( { path: '/matt-watson/secure-blocks/v1/user-roles/' } )
                .then( userRoles => {
                    return actions.setUserRoles( userRoles );
                } )
            yield userRoles;
        },
    },

} );

This sets the state of the userRoles and returns the userRoles once resolved.

You can then access this like so:

....

edit: withSelect( ( select ) => {
                return {
                    roles: select('matt-watson/secure-block').receiveUserRoles(),
                };
            } )( props => {

....

up vote 0 down vote accepted

It's worth noting that the answer above is out of date. The data store should now look like this:

const actions = {
    setUserRoles( userRoles ) {
        return {
            type: 'SET_USER_ROLES',
            userRoles,
        };
    },
    receiveUserRoles( path ) {
        return {
            type: 'RECEIVE_USER_ROLES',
            path,
        };
    },
};

const store = registerStore( 'matt-watson/secure-block', {
    reducer( state = { userRoles: {} }, action ) {

        switch ( action.type ) {
            case 'SET_USER_ROLES':
                return {
                    ...state,
                    userRoles: action.userRoles,
                };
        }

        return state;
    },

    actions,

    selectors: {
        receiveUserRoles( state ) {
            const { userRoles } = state;
            return userRoles;
        },
    },

    controls: {
        RECEIVE_USER_ROLES( action ) {
            return apiFetch( { path: action.path } );
        },
    },

    resolvers: {
        * receiveUserRoles( state ) {
            const userRoles = yield actions.receiveUserRoles( '/matt-watson/secure-blocks/v1/user-roles/' );
            return actions.setUserRoles( userRoles );
        },
    },
} );

I've updated my tutorial: https://mwatson.co.uk/working-with-gutenberg-and-the-wordpress-rest-api/

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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