Very simple wordpress block to display posts from an api call

I've been banging my head on this for a bit now.

I'm trying to create a simple wordpress block that fetches custom post types from the rest api, then displays the fetched posts via react. It only needs to do this, and requires no other editor functionality.

However, I'm a bit of a react/wp noob and I may be fundamentally misunderstanding how wordpress react functions, as I can't seem to get anywhere.

Here is my code so far:

class oupSeriesBlock extends Component {

    constructor(props) {
        super(props);
        this.state = {data: []};
    }

    getOupSeries() {
        console.log('mounted');
        apiFetch({
            path: 'wp/v2/oup_series'
        }).then((response) = {
            this.state = {data: response}
            console.log(this.state);
        })
    }

    componentDidMount() {
        this.getOupSeries();
    }

    render() {
        return(
            div
                Test
                {this.state.data.length  0 ? this.state.data.map(data = div{data.id}/div) : 'empty'}
            /div
        )
    }
}

registerBlockType('cb/oup-series', {
    title: 'OUP Book Series',
    apiVersion: 2,
    category: 'cb-layout',
    icon: 'book-alt',
    description: 'Shows list of OUP book series',
    keywords: ['book', 'series', 'oup'],
    edit: () = {
        const blockProps = useBlockProps();
        return (
            div {...blockProps}
                divOUP Series List/div
            /div
        )
    },
    save: oupSeriesBlock
});

The block is available and rendering without error but is not displaying any data, only 'Test' is rendered.

The rest route is definitely functioning correctly as I've tested it, but componentDidMount() is never being called.

this.state.data.map also works correctly when constructed with dummy data.

I've read through multiple examples and tutorials, but I'm having trouble applying them to my problem, if anyone could help it would be greatly appreciated.

Topic rest-api custom-post-types Wordpress javascript

Category Web


This is because when your block was rendered for save the API call had not finished. Save components do not run on the frontend.

    render() {
        return(
            <div>
                Test
                {this.state.data.length > 0 ? this.state.data.map(data => <div>{data.id}</div>) : 'empty'}
            </div>
        )
    }

The purpose of a save component is to take your blocks attributes, and turn them into static HTML to be saved in the post content. None of the code in your save component executes on the frontend. Your save component cannot have side effects or lifecycle methods.

In order to implement fetching posts from the API endpoint when the block is viewed by frontend users, you need to enqueue a javascript file, identify all the places your block is used, and fetch the data. This is not different to when a shortcode has frontend javascript. The main difference here is that WordPress has hooks and filters to let you only enqueue the blocks frontend assets when it's actually used.

In summary:

  • Save components can't have state, side effects, or pull data from external sources such as editor state or remote APIs
  • Save components don't run on the frontend
  • Only the static serialised output of a save component is saved, not the react component itself
  • A save component must always return the same output given the same block attributes, or it is built incorrectly and will fail block validation
  • Use functional components so that you can use newer versions of the block API and hooks such as useBlockProps for better performance and features.
  • frontend javascript requires a separate frontend JS file to be enqueued

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.