8

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.

4
  • I would note that ... is also valid javascript, as the object spread operator
    – Tom J Nowell
    Aug 14, 2018 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, 2018 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! Aug 14, 2018 at 18:29
  • Hmm, no luck importing @wordpress/data, I can get the use functions, but not a lot happens. Aug 14, 2018 at 19:59

2 Answers 2

5

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/

2
  • 2
    Thank you! But you could have edited your answer instead of writing a new one. Jan 31, 2019 at 9:57
  • it lacks state updates (requesting, resolved, failed) Dec 10, 2019 at 21:33
4

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 => {

....

1

Your Answer

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

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