Use page Title in Gutenberg custom banner block

Gutenberg stores the current editor state using wp.data, which is an abstraction over Redux. To get the title (or 100+ other values), we need to query the core/editor data store. Gutenberg makes it simple to retrieve post attributes with getEditedPostAttribute.

Once we know where to look, getting the title is simple:

const { select } = wp.data;
const title = select("core/editor").getEditedPostAttribute( 'title' );

That works, but it's not responsive. When the post title changes, title won't reflect the new value. That's kind of a let down.

To reflect changes to the editor title, we need to listen for changes to the core/editor data store. There are a few ways to do this.

One solution is to define a simple change handler function and subscribe it to data store updates:

const { select } = wp.data;

function logTitle() {
  const title = select("core/editor").getEditedPostAttribute( 'title' );
  console.log("Editor Title:", title);
}
subscribe(logTitle);

That will fire when any wp.data store value is updated -- which happens a lot.

What seems to be the Gutenberg-sanctioned way of including data-store values is to use a higher-order component to include the value directly:

const GetTitle = props => <div>{props.title}</div>;

const selectTitle = withSelect(select => ({
  title: select("core/editor").getEditedPostAttribute( 'title' )
}));
const PostTitle = selectTitle(GetTitle);

Then in the block's output, include a <PostTitle /> jsx tag. That's a lot cleaner than nested callbacks or another change handler.

Higher-order components can be difficult to follow. The short explanation is that they wrap a existing component, generate some data, then return a copy of the component with the new data passed as props. This separates logic from presentation and helps with maintainability.

GetTitle is simple enough, it's just a small component that takes in a props object with a title key and spits out some html.

withSelect is a function constructor or decorator. It accepts a function argument, and returns a new function which expects a component. Normally the returned function is invoked immediately (sort of an IIFE) but I stored it in the selectTitle variable for clarity. The new function generates an object containing the title, this object will be passed as props to any components passed to withSelect. Through some magic this will be called whenever the data store is updated.

In the end, PostTitle contains the function result of selectTitle which is a component pre-populated with the the generated props. This component can then be placed into our markup using a <PostTitle /> tag. Whenever the editor data-store is updated, the higher-level component will reflect the new data.