The bug occurs when the render method of one components directly returns another component whose root tag changes (e.g. triggered by some external event).
Running example: http://jsfiddle.net/rgmob1uo/
After clicking the "Switch to 1" button, the initial render works, but switching back breaks. Comp1 gets unmounted, but the Switcher doesn't redraw properly.
Contrast this with the version where the root element of the component (Comp1) doesn't change: http://jsfiddle.net/bz3j5n9u/
Wrapping the element returned by the Switcher in a div is a workaround: http://jsfiddle.net/6ef6ekcn/
Note that this breaks preact-route, when routed components dynamically change their root tag. AFAIK, this is either a bug or at least undocumented.
Interesting, so the change in tag name is maybe causing an unmount of the parent. I will try to migrate your repro into the tests and solve it there!
Unfortunately the new title isn't entirely representative of the problem. Even when no text component is involved, the issue can occur, for example: http://jsfiddle.net/e8kmpv1f/
@FlorianDold Ack! Sorry about that, looks like I changed it a little preemptively (thought I had found the bug)
Hi @developit, since we are going to use preact with our new product recently, any clue or any thoughts of it that we can help on this? 馃檱
I'm usually quicker to fix these types of things, just have been a little burried lately with work and life things 馃槾
I'll try to at least diagnose the issue tomorrow, that way I can explain what's happening and if I don't fix it soon enough others can jump in. It just seems like an edge case whether insertBefore() isn't getting called, likely in diff.js. Will post more info as soon as I can!
In @FlorianDold 's sample, click the buttons twice every time will prevent the error occurred. 馃槅
Found a fix :)
May I know the branch (or the fix)? I'm very curious about how you solved it. 馃檹
(And I can also check it to see if it also solved my issue.)
It was hilariously small:
https://github.com/developit/preact/compare/fix-issue-349
if you're wanting to test locally but don't know how to get it set up, ping me on Gitter. you'll likely want to use npm link.
Yes, I use npm link to test it. Thanks. I also use proxy to test it on jsfiddle recently.
It works for one of my side projects but I can not test it for my main task currently due to our dev lab is down, sorry. The fix should work for it I think. Thank you @developit!
Oops, unfortunately, the fix https://github.com/developit/preact/compare/fix-issue-349 didn't fix the issue of my main task...... 馃槶
Still got
preact.js:373 Uncaught (in promise) DOMException: Failed to execute 'replaceChild' on 'Node': The new child element contains the parent.
at Error (native)
at renderComponent (webpack:///../preact/dist/preact.js?:373:71)
at setComponentProps (webpack:///../preact/dist/preact.js?:311:103)
at buildComponentFromVNode (webpack:///../preact/dist/preact.js?:417:13)
at idiff (webpack:///../preact/dist/preact.js?:187:48)
at innerDiffNode (webpack:///../preact/dist/preact.js?:259:21)
at idiff (webpack:///../preact/dist/preact.js?:201:69)
at diff (webpack:///../preact/dist/preact.js?:168:19)
at renderComponent (webpack:///../preact/dist/preact.js?:368:32)
at setComponentProps (webpack:///../preact/dist/preact.js?:311:103)
I'll try to simplify our code to a simple version to reproduce it later.
@andretw might actually be seeing #373 now.
I built 6.4.0 myself and still got:
preact.js:374 Uncaught (in promise) DOMException: Failed to execute 'replaceChild' on 'Node': The new child element contains the parent.
at Error (native)
at renderComponent (webpack:///../preact/dist/preact.js?:374:36)
at setComponentProps (webpack:///../preact/dist/preact.js?:311:103)
at buildComponentFromVNode (webpack:///../preact/dist/preact.js?:421:13)
at idiff (webpack:///../preact/dist/preact.js?:187:48)
at innerDiffNode (webpack:///../preact/dist/preact.js?:259:21)
at idiff (webpack:///../preact/dist/preact.js?:201:69)
at diff (webpack:///../preact/dist/preact.js?:168:19)
at renderComponent (webpack:///../preact/dist/preact.js?:368:32)
at setComponentProps (webpack:///../preact/dist/preact.js?:311:103)
@andretw seems like you're seeing a different issue - the original issue here is fixed in 6.4: http://jsfiddle.net/rgmob1uo/
Any idea what's you're re-rendering to trigger that replaceChild issue?
@developit I'm seeing this error on the initial mount. It's with an internal component, but I'll try to see if I can reproduce with a public version.
@Aweary might be a recycler issue (I'm not aware of any currently, but who knows). Repro would be super useful for sure.
Also, just since I've seen some related stuff before - are you seeing this with preact/devtools enabled or disabled?
Most helpful comment
It was hilariously small:
https://github.com/developit/preact/compare/fix-issue-349
if you're wanting to test locally but don't know how to get it set up, ping me on Gitter. you'll likely want to use
npm link.