Skip to content

Register set-as-homepage and set-as-posts-page as entity actions #76668

@chihsuan

Description

@chihsuan

What problem does this address?

The set-as-homepage and set-as-posts-page actions are not registered through the entity action system. They are manually appended inside usePostActions() as React hook-based actions, bypassing the Redux store entirely.

This means unregisterEntityAction('postType', 'page', 'set-as-posts-page') has no effect — the standard API doesn't work for these two actions, unlike every other post action (view, duplicate, rename, trash, etc.).

This makes it impossible for consumers (e.g., hosted WordPress platforms that manage reading settings differently) to hide or customize these actions without patching Gutenberg internals.

Background

In the original PR (#65426), the actions initially used select() inside isEligible to read site settings. During code review, this was explicitly rejected:

"yes, isEligible should not use select at all." — @youknowriad

"We should avoid using the global select entirely because it can break easily, we're not sure that we're using the right data store by doing that. It's an API that is only meant for plugins and for very specific situations." — @youknowriad

The actions were then refactored to use useSelect hooks, which meant they couldn't be registered through registerPostTypeSchema (an async thunk, not a React component). This is why they ended up being manually appended in usePostActions().

What is your proposed solution?

Approach A: Keep hooks, add reactive registration via useEffect

Keep the actions as React hooks (useSetAsPostsPageAction / useSetAsHomepageAction) but add a useEffect in usePostActions to call registerEntityAction() / unregisterEntityAction() reactively as the hook values change. This avoids the select() concern raised in the original review while making the actions part of the store.

useEffect(() => {
    if (shouldShowHomepageActions) {
        registerEntityAction('postType', postType, setAsHomepageAction);
        registerEntityAction('postType', postType, setAsPostsPageAction);
    } else {
        unregisterEntityAction('postType', postType, 'set-as-homepage');
        unregisterEntityAction('postType', postType, 'set-as-posts-page');
    }
}, [shouldShowHomepageActions, setAsHomepageAction, setAsPostsPageAction]);

Cons:

  • useEffect runs after render, so there's a brief window where the actions may not yet be in the store.
  • The action objects are recreated by useMemo whenever pageOnFront or pageForPosts changes, triggering re-registration dispatches.
  • These two actions still follow a different registration pattern than other actions.

Approach B: Convert to plain action objects

Convert the hooks to plain action objects with select(coreStore) calls inside isEligible(), then register them in registerPostTypeSchema.

Cons:

  • Uses global select() in isEligible, which was explicitly rejected in the original PR review (Data Views: Add action for pages to set site homepage #65426). The global select bypasses the registry and could reference the wrong store instance in multi-registry contexts (e.g., iframed editors).
  • Other registered actions avoid this because their isEligible only uses item properties, not store data.

Approach C: Extend the action interface to pass registry

Add registry as a parameter to isEligible(item, registry) so actions can safely read store data without the global select. This would allow these actions to be plain objects registered in registerPostTypeSchema while respecting the registry context.

Cons:

  • Requires changes to the DataViews action interface, which is a bigger scope change.
  • Needs coordination with the @wordpress/dataviews package.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions