fix: detach reused components from their old collection in resetFromString#6775
fix: detach reused components from their old collection in resetFromString#6775DavidHarvey wants to merge 3 commits into
resetFromString#6775Conversation
|
Thanks for the PR @DavidHarvey I agree the stale-parent issue seems real, but I’m still a bit uneasy about the fix as written. From what I understand, the broken case is specifically when resetFromString reuses an existing component by id and that component is supposed to move under a different parent. In that scenario, detaching it from the old collection makes sense. What gives me pause is that this now detaches every reused component unconditionally, even when it isn’t actually moving. I suspect that’s probably fine in practice, but it feels broader than the bug being fixed. Would it make sense to only detach when the reused component is being inserted into a different collection/parent? |
Problem
resetFromStringreuses existing component models byid(viagetComponentsFromDefs) rather than rebuilding them. When a reused model lands under a new parent, it gets added to the new collection but never removed from the old one. Backbone only lets a model belong to one collection, so the move half-happens:model.collectionis never reassigned, soparent()still points at the old parent.Repro
Wrapper contains:
Delete the
<div>so it resets to just<p id="i8sd">…</p>. The<p>is correctly reused and moved up to the body, butp.parent()still returns the deleted<div>. Anything that walks up the tree from there (RTE re-parenting, layers, sorter) ends up on a dead node.Fix
Detach the reused model from its current container before re-inserting it, the same way
Component.append()already does when moving a model:It has to be
silent- a normal remove firesremoveon the old collection, which gets forwarded to symbol instances and deletes the wrong thing. The silent remove just clears the old reference; the followingresethandles rendering and symbol sync as usual.Tests
Added a regression test in
Component.tsfor the case above (reused<p>is the same instance, stays incomponentsById, old<div>is gone, andparent()/collectionpoint at the wrapper). Fails onmain, passes with the fix.