Skip to content

Fix autosave form reset bug#302

Open
ideepakchauhan7 wants to merge 20 commits intoemdash-cms:mainfrom
ideepakchauhan7:fix-autosave-reset
Open

Fix autosave form reset bug#302
ideepakchauhan7 wants to merge 20 commits intoemdash-cms:mainfrom
ideepakchauhan7:fix-autosave-reset

Conversation

@ideepakchauhan7
Copy link
Copy Markdown
Contributor

What does this PR do?

Fixes a bug where autosave invalidates the query cache and resets form fields to server state, causing user edits to be lost.

When editing a content entry with many custom fields, autosave fires after 2 seconds of inactivity. Upon success, it was calling queryClient.invalidateQueries(["content", collection, id]), which triggered a refetch from the server. This refetch updated the item prop, which triggered a useEffect in ContentEditor that resets form state (formData, slug, etc.) to server values.

The fix removes the queryClient.invalidateQueries() call from the autosaveMutation onSuccess handler. The local form state remains the source of truth during editing. Manual saves still properly invalidate and refresh the cache.

Closes #295

Type of change

  • Bug fix

Checklist

  • I have read CONTRIBUTING.md
  • pnpm typecheck passes (pre-existing errors in admin package unrelated to this change)
  • pnpm --silent lint:json | jq '.diagnostics | length' returns 0 (pre-existing errors unrelated to this change)
  • pnpm format has been run
  • I have added a changeset (if this PR changes a published package)

Autosave was invalidating the query cache after completion, which
triggered a refetch of content data from the server. This refetch
updated the item prop, causing a useEffect in ContentEditor to
reset form state to the server values, overwriting unsaved user
changes.

The fix removes the queryClient.invalidateQueries() call from the
autosaveMutation onSuccess handler. The local form state remains
the source of truth during editing, and manual saves still properly
invalidate and refresh the cache.

Fixes emdash-cms#295
Copilot AI review requested due to automatic review settings April 6, 2026 09:43
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 6, 2026

🦋 Changeset detected

Latest commit: 5cb7360

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 9 packages
Name Type
@emdash-cms/admin Patch
emdash Patch
@emdash-cms/cloudflare Patch
@emdash-cms/auth Patch
@emdash-cms/blocks Patch
@emdash-cms/gutenberg-to-portable-text Patch
@emdash-cms/x402 Patch
create-emdash Patch
@emdash-cms/plugin-embeds Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 6, 2026

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes the content editor autosave behavior so that successful autosaves no longer trigger a React Query refetch that resets in-progress form edits back to server state.

Changes:

  • Removes queryClient.invalidateQueries(["content", collection, id]) from the autosave mutation onSuccess handler.
  • Keeps autosave feedback via lastAutosaveAt while leaving manual save/publish flows to continue invalidating queries as before.
  • Adds a changeset to release the admin package as a patch.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
packages/admin/src/router.tsx Stops autosave from invalidating the content query cache, preventing editor form state resets after autosave.
.changeset/fix-autosave-form-reset.md Records the bugfix for a patch release of @emdash-cms/admin.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@ideepakchauhan7
Copy link
Copy Markdown
Contributor Author

I have read the CLA Document and I hereby sign the CLA

github-actions bot added a commit that referenced this pull request Apr 6, 2026
@ascorbic
Copy link
Copy Markdown
Collaborator

Can you fix the conflicts?

@ideepakchauhan7
Copy link
Copy Markdown
Contributor Author

I’m resolving the merge conflicts now and will push an updated branch shortly.

@ideepakchauhan7
Copy link
Copy Markdown
Contributor Author

Conflicts are fixed now. I merged the latest main into this branch and pushed the updated branch.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 11, 2026

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/@emdash-cms/admin@302

@emdash-cms/auth

npm i https://pkg.pr.new/@emdash-cms/auth@302

@emdash-cms/blocks

npm i https://pkg.pr.new/@emdash-cms/blocks@302

@emdash-cms/cloudflare

npm i https://pkg.pr.new/@emdash-cms/cloudflare@302

emdash

npm i https://pkg.pr.new/emdash@302

create-emdash

npm i https://pkg.pr.new/create-emdash@302

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/gutenberg-to-portable-text@302

@emdash-cms/x402

npm i https://pkg.pr.new/@emdash-cms/x402@302

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/@emdash-cms/plugin-ai-moderation@302

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/@emdash-cms/plugin-atproto@302

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/@emdash-cms/plugin-audit-log@302

@emdash-cms/plugin-color

npm i https://pkg.pr.new/@emdash-cms/plugin-color@302

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/@emdash-cms/plugin-embeds@302

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/@emdash-cms/plugin-forms@302

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/@emdash-cms/plugin-webhook-notifier@302

commit: 5cb7360

@github-actions github-actions bot added size/M and removed size/S labels Apr 11, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Overlapping PRs

This PR modifies files that are also changed by other open PRs:

This may cause merge conflicts or duplicated work. A maintainer will coordinate.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +661 to +665
onSuccess: () => {
setLastAutosaveAt(new Date());
// Invalidate content and draft revision so stale cached data
// doesn't overwrite the form via the sync effect
void queryClient.invalidateQueries({ queryKey: ["content", collection, id] });
if (rawItem?.draftRevisionId) {
void queryClient.invalidateQueries({
queryKey: ["revision", rawItem.draftRevisionId],
});
}
// Keep the editor's local state as the source of truth during autosave.
// Invalidating here can refetch slightly older server data and reset the form
// while the user is still typing.
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the invalidate/refetch on autosave means the local react-query cache for ["content", collection, id] never gets updated with the mutation result. For revision-enabled collections, autosave can create a new draftRevisionId (see core runtime: packages/core/src/emdash-runtime.ts:1534-1549), so leaving the cache stale can cause the editor UI (e.g., Pending changes badge / Publish changes vs Unpublish actions) to remain out of sync until a manual save or reload.

Consider updating the query cache with the autosave mutation result (or at least the revision pointer metadata) in a way that does not trigger the form-reset effect (e.g., store draftRevisionId/updatedAt in separate local state, or adjust the ContentEditor sync effect to ignore autosave-driven item updates).

Copilot uses AI. Check for mistakes.
Comment on lines +661 to +665
onSuccess: () => {
setLastAutosaveAt(new Date());
// Invalidate content and draft revision so stale cached data
// doesn't overwrite the form via the sync effect
void queryClient.invalidateQueries({ queryKey: ["content", collection, id] });
if (rawItem?.draftRevisionId) {
void queryClient.invalidateQueries({
queryKey: ["revision", rawItem.draftRevisionId],
});
}
// Keep the editor's local state as the source of truth during autosave.
// Invalidating here can refetch slightly older server data and reset the form
// while the user is still typing.
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is meant to prevent form values from reverting after autosave, but the current tests only cover that a second autosave isn’t queued. Please add a regression assertion (unit or e2e) that edits in a field are still present after an autosave completes (i.e., the input value doesn’t reset to the previous server state).

Copilot uses AI. Check for mistakes.
Comment on lines +663 to +665
// Keep the editor's local state as the source of truth during autosave.
// Invalidating here can refetch slightly older server data and reset the form
// while the user is still typing.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of removing the invalidation, could you optimistically patch the cache insgtead. Soemthing liek this:

Suggested change
// Keep the editor's local state as the source of truth during autosave.
// Invalidating here can refetch slightly older server data and reset the form
// while the user is still typing.
// Optimistically update the cache so it stays fresh
// without triggering a refetch
queryClient.setQueryData(
["content", collection, id],
(old) => old ? { ...old, data: variables.data ?? old.data, slug: variables.slug ?? old.slug, updatedAt: new Date().toISOString() } : old
);

(not checked)

await expect.element(savedBtn).toBeDisabled();
});

it("does not queue another autosave after a successful autosave", async () => {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This tests doesn't actually test the bug that this is fixing. Could you add a regressoin test?

@github-actions github-actions bot added size/L and removed size/M labels Apr 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Autosave invalidates query cache and resets form fields to server state

3 participants