Very simple wordpress block to display posts from an api call

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