Hello!
I have a bit off-topic question regarding preact internals:
I'm doing a small hobby project in which i am creating a vdom library that can render components(like preact but super simplified) and i'm wondering how react handles the vdom diffing when a component changes state.
Lets say i have this structure:
document.getElementById('root').appendChild(
<div>
Some text
<span>
Some text
<SomeComponent />
</span>
<p>More text</p>
</div>
)
Lets now say that SomeComponent has a state change and has to re-render. Does preact patch the the whole vdom or just the SomeComponent and its children?
Currently, if anything changes anywhere, i have to diff & patch the whole vdom tree like this:
const $root = document.getElementById('root')
patch($root, newVdom, oldVdom)
Are you doing something smart to diff only a part of the vdom? I would like to do something like this when something changes in my component:
patch(component.$parentElement, newVdom, oldVdom)
Am i missing something by thinking like this? I tried to go through the source code of Preact but it was a bit too much to wrap my head around exactly how the updates works.
Again, a bit off-topic but i couldn't help myself. I'm curious how you guys deal with it!
Hi there! You're right to think way - preact re-renders starting from the point where state changed. It's a nice little optimization!
@developit Thanks for your prompt reply! Do you have any hint on how to implement something like this?
I've made a simple vdom and on top of that a layer to allows me to render components(patch($root, <SomeComponent />) where <SomeComponent /> goes into h() which in turn does new SomeComponent(props).render() returning the virtual dom tree.) but i'm not sure how i am going to partially diff and patch that part of the dom once a components state has changed(via setState). The component itself doesn't know about either the vdom or the real dom.
I've been sitting all evening with pen & paper, trying to come up with a solution but every time i come up with an idea that might work i find myself overseeing something :smile:
You'll need to keep a reference or mapping between the component and it's DOM representation. Preact does this by hanging the DOM node off of components as .base. This is also useful for components that need to access their DOM after mounting.
By contrast, react uses an internal map.
Ah, yes but won't you need a reference to the last vtree of the component as well? In my head i see the component running a patch on itself like so:
class Component {
setState (state) {
...
this.lastVtree = patch($base, this.render(), this.lastVtree)
}
}
class SomeComponent extends Component {...}
But then i would have the problem of the vnode's parent tree not being up to date. The root patch($root, <Application />) would still reference the initial vtree of SomeComponent
I will look more at the source code of Preact to try to wrap my head around this. Thanks a lot for the answers!
You could do that, yes. Preact actually diffs vdom against the real DOM, but many diff against the previous trees.
Diffing against the real DOM makes sense. I'll continue with this approach for now and look around in the source of preact. Closing this, thanks again. Inspiring stuff you've done with Preact! :+1:
Most helpful comment
Hi there! You're right to think way - preact re-renders starting from the point where state changed. It's a nice little optimization!