Skip to content

fix(dashboard): Email layout name saving issue fixes NV-7084#10045

Merged
scopsy merged 1 commit intonextfrom
cursor/NV-7084-email-layout-name-reliability-3d23
Feb 16, 2026
Merged

fix(dashboard): Email layout name saving issue fixes NV-7084#10045
scopsy merged 1 commit intonextfrom
cursor/NV-7084-email-layout-name-reliability-3d23

Conversation

@scopsy
Copy link
Contributor

@scopsy scopsy commented Feb 15, 2026

What changed? Why was the change needed?

This PR resolves NV-7084, addressing the unreliable update of email layout names. Users reported that changes were often overridden, as the client sent duplicate API calls: one with the new name and another with the old name.

Root Cause:

  1. Event Bubbling: The settings drawer form (layout-settings) is rendered within the React component tree of the main editor form (edit-layout). Despite the settings drawer using a Radix Sheet portal (separate DOM), React's synthetic submit events bubble up the component tree. This caused both forms to submit simultaneously. The main form, always submitting the layout?.name (the old server value), would override the new name sent by the settings drawer.
  2. Form Control & Race Conditions: The useForm hook in the settings drawer was using the values prop, making it a "controlled" form that continuously re-synced with external layout data. This led to unexpected resets and race conditions during submission, potentially sending stale data.

Changes:

  1. Prevented Event Bubbling: Added e.stopPropagation() to the settings drawer form's onSubmit handler to stop the submit event from reaching the parent main form.
  2. Improved Form State Management:
    • Removed the values prop from useForm in the settings drawer.
    • Implemented a useEffect with wasOpenRef to reset the form only when the drawer transitions from closed to open, ensuring fresh data on open without interfering with mid-edit changes.
    • Reset the form with the mutation response data upon successful save to maintain a clean state before the drawer closes.

Screenshots

N/A

Expand for optional sections

Related enterprise PR

Special notes for your reviewer

The core issue was the interaction between nested forms in the React component tree, where synthetic events bubble, even when using portals that separate DOM elements. The e.stopPropagation() on the settings drawer's form submission is crucial to prevent the parent form from also submitting.


Linear Issue: NV-7084

Open in Cursor Open in Web

…t name

The settings drawer form (layout-settings) is rendered inside the main
editor form (edit-layout) via React component tree. Even though the
Sheet uses a Radix portal, React's synthetic submit events bubble
through the component tree, causing both forms to fire on a single
submit - one with the new name from the drawer, and another with the
old name from the server, which overrides the update.

Changes:
- Add e.stopPropagation() to the settings drawer form's onSubmit to
  prevent the submit event from bubbling to the parent form
- Remove the values prop from useForm which was causing the form to
  re-sync with server data during submission, leading to race conditions
- Add useEffect to reset form values only when the drawer transitions
  from closed to open (not on every layout data change)
- Reset form with response data on successful save to keep form state
  clean before the drawer closes

Fixes NV-7084

Co-authored-by: Dima Grossman <dima@grossman.io>
@cursor
Copy link
Contributor

cursor bot commented Feb 15, 2026

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@linear
Copy link

linear bot commented Feb 15, 2026

@netlify
Copy link

netlify bot commented Feb 15, 2026

Deploy preview added

Name Link
🔨 Latest commit 1ea260e
🔍 Latest deploy log https://app.netlify.com/projects/dashboard-v2-novu-staging/deploys/69924118657d8a0008556cdf
😎 Deploy Preview https://deploy-preview-10045.dashboard-v2.novu-staging.co
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
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 unreliable email layout name updates in the layout editor by preventing nested form submissions and stabilizing the settings drawer form state so it doesn’t re-sync mid-edit.

Changes:

  • Stop React synthetic submit event bubbling from the settings drawer form to the parent editor form.
  • Remove react-hook-form values usage and reset the drawer form only when the drawer opens.
  • Reset the drawer form with mutation response data after a successful save.

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

Comment on lines +86 to +96
const wasOpenRef = useRef(false);
useEffect(() => {
if (isOpen && !wasOpenRef.current && layout) {
form.reset({
name: layout.name || '',
layoutId: layout.layoutId || '',
isTranslationEnabled: layout.isTranslationEnabled || false,
});
}
wasOpenRef.current = isOpen;
}, [isOpen, layout, form]);
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

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

The form reset logic only runs on the closed→open transition. If the layout query is invalidated/refetched (e.g., after saving) and the user reopens the drawer before the refetch completes, the drawer can reset to stale layout data and then won’t resync when the fresh layout arrives while open (because wasOpenRef is already true). That can reintroduce the “old name overwrites new name” behavior if the user submits again. Consider also resetting when layout changes while the drawer is open and the form is still pristine (e.g., track last-synced layout.updatedAt/layout._id in a ref and call form.reset when it changes and !form.formState.isDirty).

Copilot uses AI. Check for mistakes.
@scopsy scopsy changed the title Email layout name reliability fix(dashboard): Email layout name saving issue fixes NV-7084 Feb 16, 2026
@scopsy scopsy marked this pull request as ready for review February 16, 2026 12:53
@scopsy scopsy merged commit 13a6f45 into next Feb 16, 2026
34 of 36 checks passed
@scopsy scopsy deleted the cursor/NV-7084-email-layout-name-reliability-3d23 branch February 16, 2026 12:55
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 16, 2026

Caution

Review failed

The pull request is closed.

Walkthrough

The layout editor settings drawer component is modified to improve form state management. The changes introduce useEffect and useRef imports, remove initial values from form initialization, and add logic to reset the form when the drawer opens with a layout present. The updateLayout success handler is updated to accept returned data and reset the form using specific properties. The onSubmit handler is refactored to stop event propagation and explicitly invoke form.handleSubmit with the event parameter.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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.

3 participants