Hi,
I've discovered that preact does a few DOM updates which are not necessary.
Since its hard to explain I've created a minimal example repository (https://github.com/KnisterPeter/preact-rerender-bug) to show the effect.
I'll try to explain it anyway:
Given one renders a component with an empty div and a ref attached to it and in the update-lifecycle callback render another application into that div (e.g. some plugin concept).
When the plugin component is updated (via its props) it is getting rerendered (as expected) but in contrast to react the 'contained application' will get remounted.
This results in lifecycle problems.
Any idea whats going on here?
Hmm, I would recommend very strongly against rendering a preact tree within another preact tree. I didn't realize that was something people wanted to do.
Why do you recommend against this? First of all in react its possible, but thats the weakest argument. :smile:
The reason for this (in my case) is a separation of application parts which might not even be written using the same technology. So in the give example repo everything is preact for simplicity, but it could be as well react.js, anguar or whatever else.
This my not be the best choice to use several frontend techs to build an application but in reality this happends and e.g. legacy applications must stay supported and could not be rewritten adhoc.
So can you please give a bit more detail on why you would not recommand it? And is there a fix for this or are you open for PR?
It's definitely an interesting case. The issue is caused by Preact not being able to tell that it's crossing another render root boundary - the render()'d elements just look like they were created with Preact, so it diffs into them. We could probably fix this by annotating any render() root element with a property that Preact would then detect and avoid recursing into from the parent diff.
Interestingly, it works fine if there's a non-preact element wrapping the render root, because that prevents the parent tree from recursing into the child.
I do think you've got a valid use-case here, and we're likely to see more of the exact type of thing you're doing as people adopt Preact with Web Components (particularly for those not using Shadow DOM, which avoids this issue).
Most helpful comment
It's definitely an interesting case. The issue is caused by Preact not being able to tell that it's crossing another render root boundary - the render()'d elements just look like they were created with Preact, so it diffs into them. We could probably fix this by annotating any render() root element with a property that Preact would then detect and avoid recursing into from the parent diff.
Interestingly, it works fine if there's a non-preact element wrapping the render root, because that prevents the parent tree from recursing into the child.
I do think you've got a valid use-case here, and we're likely to see more of the exact type of thing you're doing as people adopt Preact with Web Components (particularly for those not using Shadow DOM, which avoids this issue).