3

I have a block that renders titles of all existing posts in the <Modal/>. I retrieve it from the server using <ServerSideRender/> (that returns plain html). I want to be able to choose one of the titles (ideally save it in the postTitle attribute) and display it in the block.

attributes: {
    postTitle: {
        type: 'string'
    }
},

edit(props) {
    const { attributes } = props;
    const { postTitle } = props.attributes;

    const MyModal = withState( {
        isOpen: false,
    } )
    ( ( { isOpen, setState } ) => (
        <div>
            <Button isDefault onClick={ () => setState( { isOpen: true } ) }>Choose</Button>
            { isOpen ?
                <Modal onRequestClose={ () => setState( { isOpen: false } ) }>
                        <ServerSideRender
                            block="my-blocks/wordpress-title"
                            attributes={attributes}
                        />
                </Modal>
                : null }
        </div>
    ) );

return ([
        <InspectorControls>
            <div>
                <strong>Choose Wordpress title:</strong>
                <MyModal/>
            </div>
        </InspectorControls>,
    ]);
},

Is there any sensible way to retrieve data from a server, so it was possible to operate on it within a block?

  • 1
    I had a little trouble following your description, can you edit your question to include a real world example I can relate to? It wasn't clear, and some terms you used didn't seem to make sense in context, e.g. inspector. Perhaps if you explained what you were trying to do without making it super generic it would be more understandable? – Tom J Nowell Sep 5 '18 at 23:26
  • @TomJNowell Thank you for the advice. Is it clearer now? – Michal Karbownik Sep 6 '18 at 21:20
  • Why do you render my-blocks/wordpress-title on the serverside? The Gutenberg handbook states: << ServerSideRender should be regarded as a fallback or legacy mechanism, it is not appropriate for developing new features against.>> Why can't you get the list of posts through the WP REST api? – Andrei Draganescu Feb 21 at 21:11
  • @AndreiDraganescu That was mostly an 'art for art's sake' type of exercise. The goal was to create a dynamic block using the server-side rendering. Thus the question about doing it this way. – Michal Karbownik Feb 22 at 8:44
0

There are multiple better ways to get a list of posts in a Gutenberg block, other than rendering serverside.

First is to use the Wrodpress wrapper around Redux and select posts exactly like in the Gutenberg Handbook:

edit: withSelect( function( select ) {
    return {
        posts: select( 'core' ).getEntityRecords( 'postType', 'post' )
    };
} )( function( props ) {

    if ( ! props.posts ) {
        return "Loading...";
    }

    if ( props.posts.length === 0 ) {
        return "No posts";
    }
    var className = props.className;
    var post = props.posts[ 0 ];

    return el(
        'a',
        { className: className, href: post.link },
        post.title.rendered
    );
} ),

Notice how the edit function is composed with data from the Gutenberg store and it gets the posts array as a prop.

The second option is to simply use Axios to get the posts you need via the rest API:

/**
 * Makes a get request to the desired post type and builds the query string based on an object.
 *
 * @param {string|boolean} restBase - rest base for the query.
 * @param {object} args
 * @returns {AxiosPromise<any>}
 */
export const getPosts = ({ restBase = false, ...args }) => {
    const queryString = Object.keys(args).map(arg => `${arg}=${args[arg]}`).join('&');

    return axios.get(`/wp-json/wp/v2/${restBase}?        ${queryString}&_embed`);
};

This is a snippet from this great tutorial: https://github.com/bigbitecreative/gutenberg-postlist-demo

After the posts call is defined you may use componentDidMount to call it and then set the posts as the new Modal componenet state:

    /**
 * When the component mounts it calls this function.
 * Fetches posts types, selected posts then makes first call for posts
 */
componentDidMount() {
    this.setState({
        loading: true,
    });

    api.getPostTypes()
        .then(({ data = {} } = {}) => {
            this.setState({
                types: data
            }
        });
}

Also from Gutenberg Postlist demo but shortened for brevity.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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