Move renderCallbacks to VNode and queue refs as renderCallbacks#2098
Move renderCallbacks to VNode and queue refs as renderCallbacks#2098andrewiggins wants to merge 11 commits into
Conversation
| _dom: null, | ||
| _lastDomChild: null, | ||
| _component: null, | ||
| _renderCallbacks: null, |
There was a problem hiding this comment.
FYI, initializing this to an array saves us about 11 B 9B. However it does add an extra array allocation for every VNode :/ Unsure how that affects performance. Perhaps someone can investigate this and open a new PR if its worth it?
| ); | ||
|
|
||
| if ((j = childVNode.ref) && oldVNode.ref != j) { | ||
| if (!refs) refs = []; |
There was a problem hiding this comment.
Yay! This array allocation is gone! Now if you attach a ref to a component, we re-use that component's _renderCallbacks array. However, if you attach a ref to a DOM VNode, we allocate a new array (that VNode's _renderCallbacks array) for that ref. But I think the net is still fewer array allocations.
|
Hey, Could we add a test here (can be skipped) to see if the refs are bound in ComponentDidMount? Specific example: The Child for example has a span with ref={ref} and in |
|
Oh good call! Will do |
| // increment is never cleared once the component suspends. So when it | ||
| // resumes and the component is rerendered, we queue up another cDU so | ||
| // cDU is called an extra time. | ||
| expect(componentDidUpdate).to.have.been.calledThrice; |
There was a problem hiding this comment.
Since _renderCallbacks is stored on VNode now, they don't persist across renders. If a VNode suspends, it'll never get added to the commitQueue array so its _renderCallbacks won't get called. And since VNodes are recreated on each render it won't get invoked on the next render since that'll be with a newVNode, and not the one from the previous render which had the _renderCallback.
bd2635f to
acf8195
Compare
|
Size Change: -37 B (0%) Total Size: 42.3 kB
ℹ️ View Unchanged
|
… (-20 B) Some test still fail cause useLayoutEffects are scheduled before the refs are :(
Since _renderCallbacks is stored on VNode now, if a VNode suspends, it'll never get added to the commitQueue array so its _renderCallbacks won't get called. And since VNodes are recreated on each render it won't get invoked on the next render since that'll be with a newVNode
acf8195 to
dd44824
Compare
📊 Tachometer Benchmark ResultsSummaryduration
usedJSHeapSize
Results02_replace1k
duration
usedJSHeapSize
run-warmup-0
run-warmup-1
run-warmup-2
run-warmup-3
run-warmup-4
run-final
03_update10th1k_x16
duration
usedJSHeapSize
07_create10k
duration
usedJSHeapSize
filter_list
duration
usedJSHeapSize
hydrate1k
duration
usedJSHeapSize
many_updates
duration
usedJSHeapSize
text_update
duration
usedJSHeapSize
|
|
Superseded by #3860 |
In the spirit of #2011, queue the
applyRefcalls as_renderCallbacksso they are invoked after the entire DOM is updated. This change effectively undos 40212eb from #1658.I always didn't like how I had to move ref handling to
diffChildren. That had to be done in #1658 because refs needed to be unmounted first, then the new value applied, for example, if the VNode changed tag type fromdivtospan. We would need to call therefwithnullwhen thedivis unmounted, then call it again with thespanin that order. This PR accomplishes the same behavior by queuing the setting of the new ref value in_renderCallbacksafter all unmounts and DOM manipulations are done.