fix(DynamicEditableTitle): preserve in-flight edits when title prop changes#39861
fix(DynamicEditableTitle): preserve in-flight edits when title prop changes#39861
Conversation
…hanges The effect at index.tsx:88 called setCurrentTitle(title) whenever the title prop changed — including mid-edit, which clobbered unsaved typing. Gate it on !isEditing so a parent re-render with a new title doesn't overwrite what the user has typed. handleBlur already syncs currentTitle on commit, so the consistency invariant is preserved. Also fix the existing 'prop changes mid-edit do not clobber' regression test, which rerendered Harness with the same initialTitle="Foo" — the prop the component received never actually changed, so the test passed even on broken code. Rerender DynamicEditableTitle directly with a different title prop so the sync effect actually runs.
Code Review Agent Run #19886dActionable Suggestions - 0Review Details
Bito Usage GuideCommands Type the following command in the pull request comment and save the comment.
Refer to the documentation for additional commands. Configuration This repository uses Documentation & Help |
Including isEditing in the dep array re-ran the sync effect when isEditing flipped from true to false on blur — which clobbered the just-committed value if the parent's title prop hadn't propagated yet (e.g. parents that don't update local state in the onSave callback, which is also the pattern in Header.test.tsx). Read isEditing via closure instead so the effect only fires when the title prop actually changes. handleBlur still syncs currentTitle on commit, so the consistency invariant is preserved.
|
Thanks for cleaning this up — the gating is correct and the test now The fix swaps one edge case for another. With if (!isEditing), this
Before this PR, the user would have seen "Bar" appear and the blur would Probably still a net win over the original clobber bug, but if any flow Smaller suggestion: extend the new test to also assert the commit rerender(<DynamicEditableTitle {...props} title="Bar" />); Otherwise LGTM. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #39861 +/- ##
=======================================
Coverage 64.36% 64.37%
=======================================
Files 2569 2569
Lines 134745 134746 +1
Branches 31278 31279 +1
=======================================
+ Hits 86732 86738 +6
+ Misses 46515 46510 -5
Partials 1498 1498
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Code Review Agent Run #d0eedcActionable Suggestions - 0Review Details
Bito Usage GuideCommands Type the following command in the pull request comment and save the comment.
Refer to the documentation for additional commands. Configuration This repository uses Documentation & Help |
rusackas
left a comment
There was a problem hiding this comment.
The phantom-revert in handleBlur - the onSave call is unconditional on title !== formattedTitle regardless of whether the user actually typed. Quick fix is a dirtyRef set in handleChange, gated in handleBlur before calling onSave (and reset).
Pairing it with the expect(onSave).toHaveBeenCalledWith('FooX') post-blur assertion in the regression test would lock the semantics in. Happy to approve once those are in.
SUMMARY
Follow-up to #38563. The effect at
DynamicEditableTitle/index.tsx:88callssetCurrentTitle(title)whenever thetitleprop changes — including mid-edit, so a parent re-render with a new title (autosave callback, optimistic update, sibling state push) clobbers the user's unsaved typing. The previous fix only addressed thehandleChange!isEditingearly-return, not this effect.Gate the sync effect on
!isEditing.handleBlurstill callssetCurrentTitle(formattedTitle)before flippingisEditingfalse, so the consistency invariant is preserved on commit.Also fix the existing regression test that didn't actually exercise this bug. It rerendered
Harnesswith the sameinitialTitle="Foo", but Harness owns its own state and only readsinitialTitleonce — so thetitleprop the component received never actually changed. RerenderDynamicEditableTitledirectly with a differenttitleprop instead.BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
N/A — preserves user input that was previously dropped.
TESTING INSTRUCTIONS
npx jest packages/superset-ui-core/src/components/DynamicEditableTitle/DynamicEditableTitle.regression.test.tsx --watchman=false— all 3 tests pass; the third one fails on prior HEAD if you revert onlyindex.tsx.ADDITIONAL INFORMATION