@@ -14,10 +14,8 @@ import type {
1414 Instance ,
1515 Type ,
1616 Props ,
17- UpdatePayload ,
1817 Container ,
1918 ChildSet ,
20- HostContext ,
2119} from './ReactFiberHostConfig' ;
2220
2321import {
@@ -126,13 +124,36 @@ if (supportsMutation) {
126124 updateHostComponent = function (
127125 current : Fiber ,
128126 workInProgress : Fiber ,
129- updatePayload : null | UpdatePayload ,
130127 type : Type ,
131- oldProps : Props ,
132128 newProps : Props ,
133129 rootContainerInstance : Container ,
134- currentHostContext : HostContext ,
135130 ) {
131+ // If we have an alternate, that means this is an update and we need to
132+ // schedule a side-effect to do the updates.
133+ const oldProps = current . memoizedProps ;
134+ if ( oldProps === newProps ) {
135+ // In mutation mode, this is sufficient for a bailout because
136+ // we won't touch this node even if children changed.
137+ return ;
138+ }
139+
140+ // If we get updated because one of our children updated, we don't
141+ // have newProps so we'll have to reuse them.
142+ // TODO: Split the update API as separate for the props vs. children.
143+ // Even better would be if children weren't special cased at all tho.
144+ const instance : Instance = workInProgress . stateNode ;
145+ const currentHostContext = getHostContext ( ) ;
146+ // TODO: Experiencing an error where oldProps is null. Suggests a host
147+ // component is hitting the resume path. Figure out why. Possibly
148+ // related to `hidden`.
149+ const updatePayload = prepareUpdate (
150+ instance ,
151+ type ,
152+ oldProps ,
153+ newProps ,
154+ rootContainerInstance ,
155+ currentHostContext ,
156+ ) ;
136157 // TODO: Type this specific to this type of component.
137158 workInProgress . updateQueue = ( updatePayload : any ) ;
138159 // If the update payload indicates that there is a change or if there
@@ -211,54 +232,70 @@ if (supportsMutation) {
211232 updateHostComponent = function (
212233 current : Fiber ,
213234 workInProgress : Fiber ,
214- updatePayload : null | UpdatePayload ,
215235 type : Type ,
216- oldProps : Props ,
217236 newProps : Props ,
218237 rootContainerInstance : Container ,
219- currentHostContext : HostContext ,
220238 ) {
239+ const currentInstance = current . stateNode ;
240+ const oldProps = current . memoizedProps ;
221241 // If there are no effects associated with this node, then none of our children had any updates.
222242 // This guarantees that we can reuse all of them.
223243 const childrenUnchanged = workInProgress . firstEffect === null ;
224- const currentInstance = current . stateNode ;
225- if ( childrenUnchanged && updatePayload === null ) {
244+ if ( childrenUnchanged && oldProps === newProps ) {
226245 // No changes, just reuse the existing instance.
227246 // Note that this might release a previous clone.
228247 workInProgress . stateNode = currentInstance ;
229- } else {
230- let recyclableInstance = workInProgress . stateNode ;
231- let newInstance = cloneInstance (
232- currentInstance ,
233- updatePayload ,
248+ return ;
249+ }
250+ const recyclableInstance : Instance = workInProgress . stateNode ;
251+ const currentHostContext = getHostContext ( ) ;
252+ let updatePayload = null ;
253+ if ( oldProps !== newProps ) {
254+ updatePayload = prepareUpdate (
255+ recyclableInstance ,
234256 type ,
235257 oldProps ,
236258 newProps ,
237- workInProgress ,
238- childrenUnchanged ,
239- recyclableInstance ,
259+ rootContainerInstance ,
260+ currentHostContext ,
240261 ) ;
241- if (
242- finalizeInitialChildren (
243- newInstance ,
244- type ,
245- newProps ,
246- rootContainerInstance ,
247- currentHostContext ,
248- )
249- ) {
250- markUpdate ( workInProgress ) ;
251- }
252- workInProgress . stateNode = newInstance ;
253- if ( childrenUnchanged ) {
254- // If there are no other effects in this tree, we need to flag this node as having one.
255- // Even though we're not going to use it for anything.
256- // Otherwise parents won't know that there are new children to propagate upwards.
257- markUpdate ( workInProgress ) ;
258- } else {
259- // If children might have changed, we have to add them all to the set.
260- appendAllChildren ( newInstance , workInProgress ) ;
261- }
262+ }
263+ if ( childrenUnchanged && updatePayload === null ) {
264+ // No changes, just reuse the existing instance.
265+ // Note that this might release a previous clone.
266+ workInProgress . stateNode = currentInstance ;
267+ return ;
268+ }
269+ let newInstance = cloneInstance (
270+ currentInstance ,
271+ updatePayload ,
272+ type ,
273+ oldProps ,
274+ newProps ,
275+ workInProgress ,
276+ childrenUnchanged ,
277+ recyclableInstance ,
278+ ) ;
279+ if (
280+ finalizeInitialChildren (
281+ newInstance ,
282+ type ,
283+ newProps ,
284+ rootContainerInstance ,
285+ currentHostContext ,
286+ )
287+ ) {
288+ markUpdate ( workInProgress ) ;
289+ }
290+ workInProgress . stateNode = newInstance ;
291+ if ( childrenUnchanged ) {
292+ // If there are no other effects in this tree, we need to flag this node as having one.
293+ // Even though we're not going to use it for anything.
294+ // Otherwise parents won't know that there are new children to propagate upwards.
295+ markUpdate ( workInProgress ) ;
296+ } else {
297+ // If children might have changed, we have to add them all to the set.
298+ appendAllChildren ( newInstance , workInProgress ) ;
262299 }
263300 } ;
264301 updateHostText = function (
@@ -290,12 +327,9 @@ if (supportsMutation) {
290327 updateHostComponent = function (
291328 current : Fiber ,
292329 workInProgress : Fiber ,
293- updatePayload : null | UpdatePayload ,
294330 type : Type ,
295- oldProps : Props ,
296331 newProps : Props ,
297332 rootContainerInstance : Container ,
298- currentHostContext : HostContext ,
299333 ) {
300334 // Noop
301335 } ;
@@ -358,39 +392,13 @@ function completeWork(
358392 const rootContainerInstance = getRootHostContainer ( ) ;
359393 const type = workInProgress . type ;
360394 if ( current !== null && workInProgress . stateNode != null ) {
361- // If we have an alternate, that means this is an update and we need to
362- // schedule a side-effect to do the updates.
363- const oldProps = current . memoizedProps ;
364- if ( oldProps !== newProps ) {
365- // If we get updated because one of our children updated, we don't
366- // have newProps so we'll have to reuse them.
367- // TODO: Split the update API as separate for the props vs. children.
368- // Even better would be if children weren't special cased at all tho.
369- const instance : Instance = workInProgress . stateNode ;
370- const currentHostContext = getHostContext ( ) ;
371- // TODO: Experiencing an error where oldProps is null. Suggests a host
372- // component is hitting the resume path. Figure out why. Possibly
373- // related to `hidden`.
374- const updatePayload = prepareUpdate (
375- instance ,
376- type ,
377- oldProps ,
378- newProps ,
379- rootContainerInstance ,
380- currentHostContext ,
381- ) ;
382-
383- updateHostComponent (
384- current ,
385- workInProgress ,
386- updatePayload ,
387- type ,
388- oldProps ,
389- newProps ,
390- rootContainerInstance ,
391- currentHostContext ,
392- ) ;
393- }
395+ updateHostComponent (
396+ current ,
397+ workInProgress ,
398+ type ,
399+ newProps ,
400+ rootContainerInstance ,
401+ ) ;
394402
395403 if ( current . ref !== workInProgress . ref ) {
396404 markRef ( workInProgress ) ;
0 commit comments