Skip to content

Add createEntityRecord for local‑only drafts in @wordpress/core‑data #74462

Open

Description

@gigitux

What problem does this address?

There is no createEntityRecord action in @wordpress/core-data, which blocks a local-first UX. The only available path is saveEntityRecord, which writes to the database immediately and forces cleanup if the user cancels.

A createEntityRecord action would allow creating a local-only entity record in the store, editing it, and saving only when the user confirms.

For instance, DataViews/DataForm is well-suited for list + form flows, but new-item creation cannot be done without persisting to the database. This prevents:

  • Draft-first creation flows (create -> edit -> save)
  • Canceling a create flow without cleanup
  • Wizard-like experiences for new items

Demo plugin

I prepared a small plugin that demonstrates the gap:

  • Admin page with a Books list rendered via DataViews
  • Book form rendered via DataForm
  • “New book (in-memory)” action that would use createEntityRecord
  • Current workaround: saveEntityRecord (draft saved immediately)

This means that the user must save data to the database before updating the entity.

CleanShot.2026-01-08.at.16.24.22.mp4

Expected behavior

  • createEntityRecord creates a local-only draft record in the store without persisting to the database.
  • The draft can be updated via editEntityRecord.
  • saveEntityRecord (or saveEditedEntityRecord) persists the draft and returns the real ID from WordPress.

Ideal experience

A local-only draft should be possible via createEntityRecord, and then updated with editEntityRecord until the user explicitly saves. The draft ID is temporary; WordPress assigns the real ID on save.

const { dispatch } = wp.data;

const draft = dispatch( 'core' ).createEntityRecord(
  'postType',
  'book',
  { title: 'New book', status: 'draft', meta: { book_author: '' } }
);

// Update the draft locally.
dispatch( 'core' ).editEntityRecord( 'postType', 'book', draft.id, {
  title: 'Updated title',
  meta: { book_author: 'New author' },
} );

// Persist only when the user confirms.
await dispatch( 'core' ).saveEntityRecord( 'postType', 'book', draft );

Activity

  1. Mamaduka commented on Jan 8, 2026

    @Mamaduka
    Member

    Thanks for the proposal, @gigitux!

    Would we be able to query these local-only drafts via getEntityRecords? Mostly curious if the new API would allow us to do some sort of optimistic updates.

    For example, when adding a new note, it needs to complete a round trip before we can display it to the user, which creates a bad UX, especially on slow connections.

  2. gigitux commented on Jan 8, 2026

    @gigitux
    ContributorAuthor

    Would we be able to query these local-only drafts via getEntityRecords? Mostly curious if the new API would allow us to do some sort of optimistic updates.

    Interesting! I think this should be possible, and we could expose it as an opt-in option.

  3. self-assigned this
    on Jan 9, 2026
  4. talldan commented on Jan 12, 2026

    @talldan
    Contributor

    The drawback to local drafts is the risk of losing data if the browser tab is closed. I think WordPress usually uses autodrafts for this purpose, to represent something that's a temporary draft but saved.

    In-memory items bring a lot of broader concerns. For example, do we need to remind the user to save if they try navigating away and how do features like 'parent' post work if the parent is only in-memory?

    Not saying I'm against the idea, but the scope might be bigger than anticipated.

  5. gigitux commented on Jan 12, 2026

    @gigitux
    ContributorAuthor

    The drawback to local drafts is the risk of losing data if the browser tab is closed. I think WordPress usually uses autodrafts for this purpose, to represent something that's a temporary draft but saved.

    I think that this issue should be handled by the consumer of the @wordpress/core-data. The consumer can check if a in-memory entity is present, and if it is, present the standard browser confirmation dialog when the user attempts to navigate away.

    In-memory items bring a lot of broader concerns. For example, do we need to remind the user to save if they try navigating away and how do features like 'parent' post work if the parent is only in-memory?

    Thanks for this context! I agree with you. I think that we should iterate and see how it goes. For now, potentially we can use unlock/lock to ensure that this API is used only across Gutenberg packages (and collect all the limitations, including this one). What do you think?

    I'm working on an initial PR here: #74497

  6. talldan commented on Jan 15, 2026

    @talldan
    Contributor

    I think that this issue should be handled by the consumer of the @wordpress/core-data.

    It has impacts on the broader ecosystem in core. Perhaps it's not too much of a concern if it's kept private. But if it's usable by extenders they can implement their own entities that are 'staged', and the problem is all the core gutenberg code that needs to be updated to ensure these staged entities are represented and work correctly in WordPress.

    I guess the question would be, is that a workload you're willing to undertake?

  7. youknowriad commented on Jan 22, 2026

    @youknowriad
    Contributor

    One use-case we have for this in Core (there's an issue about it), is that right now when you add "tags" to a post, they are created as tags. So if you make a typo and remove that tag before saving, the tag with typo was actually saved.

  8. tyxla commented on Feb 6, 2026

    @tyxla
    Member

    The drawback to local drafts is the risk of losing data if the browser tab is closed. I think WordPress usually uses autodrafts for this purpose, to represent something that's a temporary draft but saved.

    I think that this issue should be handled by the consumer of the @wordpress/core-data.

    It has impacts on the broader ecosystem in core. Perhaps it's not too much of a concern if it's kept private. But if it's usable by extenders they can implement their own entities that are 'staged', and the problem is all the core gutenberg code that needs to be updated to ensure these staged entities are represented and work correctly in WordPress.

    I agree with @talldan here that this is a risk that's worth considering. And we know of many cases when users have actually lost data because autosaves didn't trigger on time, were triggered earlier, or just didn't finish on time. Also, autosaves work only with post types, so by design, they're not a solution that works for all entities.

    I wonder if we can treat the storage mechanism as an implementation detail and therefore something that can be configured. Yes, it might make sense that sometimes we store the drafts in memory, but perhaps we might want to store them in local storage or session storage, or even some remote storage? It would be useful to have control over this, so we can implement different variants of persistence storage, potentially registered and supported by plugins.

  9. tyxla commented on Feb 6, 2026

    @tyxla
    Member

    Also, if we consider that we'd go in the direction of implementing a mechanism to store the data locally, it creates exciting opportunities for building an offline-first experience in WordPress.

  10. Mamaduka commented on Sep 30, 2026

    @Mamaduka
    Member

    Another use case from Notes: preserving unsent note and reply drafts (#73473). They're a good fit for local-only records, but there are a few requirements:

    • Never synced. editEntityRecord passes edits to the sync manager, and comments are synced when RTC is enabled. A draft shouldn't reach other collaborators before it's submitted.
    • Not dirty. Drafts shouldn't show up in __experimentalGetDirtyEntityRecords, so they stay out of the save panel, the unsaved changes warning, and the site editor's Save.
    • No undo levels. Typing a note shouldn't mix with block edits in the undo history.
  11. youknowriad commented on Sep 30, 2026

    @youknowriad
    Contributor

    @Mamaduka given these three requirements, these feel more like local state and not local only entities that should live in core-data. What benefit core-data brings for these?

  12. Mamaduka commented on Sep 30, 2026

    @Mamaduka
    Member

    @youknowriad, yeah, you're right. Notes just need "fancy" local state/cache.

    What benefit core-data brings for these?

    Mostly a single source of truth for data, but without optimistic updates, it's probably not worth it.

  13. removed their assignment
    on Oct 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions