@@ -14,10 +14,8 @@ import type {
14
14
Instance ,
15
15
Type ,
16
16
Props ,
17
- UpdatePayload ,
18
17
Container ,
19
18
ChildSet ,
20
- HostContext ,
21
19
} from './ReactFiberHostConfig' ;
22
20
23
21
import {
@@ -126,13 +124,36 @@ if (supportsMutation) {
126
124
updateHostComponent = function (
127
125
current : Fiber ,
128
126
workInProgress : Fiber ,
129
- updatePayload : null | UpdatePayload ,
130
127
type : Type ,
131
- oldProps : Props ,
132
128
newProps : Props ,
133
129
rootContainerInstance : Container ,
134
- currentHostContext : HostContext ,
135
130
) {
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
+ ) ;
136
157
// TODO: Type this specific to this type of component.
137
158
workInProgress . updateQueue = ( updatePayload : any ) ;
138
159
// If the update payload indicates that there is a change or if there
@@ -211,54 +232,70 @@ if (supportsMutation) {
211
232
updateHostComponent = function (
212
233
current : Fiber ,
213
234
workInProgress : Fiber ,
214
- updatePayload : null | UpdatePayload ,
215
235
type : Type ,
216
- oldProps : Props ,
217
236
newProps : Props ,
218
237
rootContainerInstance : Container ,
219
- currentHostContext : HostContext ,
220
238
) {
239
+ const currentInstance = current . stateNode ;
240
+ const oldProps = current . memoizedProps ;
221
241
// If there are no effects associated with this node, then none of our children had any updates.
222
242
// This guarantees that we can reuse all of them.
223
243
const childrenUnchanged = workInProgress . firstEffect === null ;
224
- const currentInstance = current . stateNode ;
225
- if ( childrenUnchanged && updatePayload === null ) {
244
+ if ( childrenUnchanged && oldProps === newProps ) {
226
245
// No changes, just reuse the existing instance.
227
246
// Note that this might release a previous clone.
228
247
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 ,
234
256
type ,
235
257
oldProps ,
236
258
newProps ,
237
- workInProgress ,
238
- childrenUnchanged ,
239
- recyclableInstance ,
259
+ rootContainerInstance ,
260
+ currentHostContext ,
240
261
) ;
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 ) ;
262
299
}
263
300
} ;
264
301
updateHostText = function (
@@ -290,12 +327,9 @@ if (supportsMutation) {
290
327
updateHostComponent = function (
291
328
current : Fiber ,
292
329
workInProgress : Fiber ,
293
- updatePayload : null | UpdatePayload ,
294
330
type : Type ,
295
- oldProps : Props ,
296
331
newProps : Props ,
297
332
rootContainerInstance : Container ,
298
- currentHostContext : HostContext ,
299
333
) {
300
334
// Noop
301
335
} ;
@@ -358,39 +392,13 @@ function completeWork(
358
392
const rootContainerInstance = getRootHostContainer ( ) ;
359
393
const type = workInProgress . type ;
360
394
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
+ ) ;
394
402
395
403
if ( current . ref !== workInProgress . ref ) {
396
404
markRef ( workInProgress ) ;
0 commit comments