@@ -295,6 +295,79 @@ describe('Profiler', () => {
295295 );
296296 });
297297
298+ it('does not report work done on a sibling', () => {
299+ const callback = jest.fn();
300+
301+ const DoesNotUpdate = React.memo(function DoesNotUpdateInner() {
302+ Scheduler.unstable_advanceTime(10);
303+ return null;
304+ }, () => true);
305+
306+ let updateProfilerSibling;
307+
308+ function ProfilerSibling() {
309+ const [count, setCount] = React.useState(0);
310+ updateProfilerSibling = () => setCount(count + 1);
311+ return null;
312+ }
313+
314+ function App() {
315+ return (
316+ <React.Fragment>
317+ <React.Profiler id="test" onRender={callback}>
318+ <DoesNotUpdate />
319+ </React.Profiler>
320+ <ProfilerSibling />
321+ </React.Fragment>
322+ );
323+ }
324+
325+ const renderer = ReactTestRenderer.create(<App />);
326+
327+ expect(callback).toHaveBeenCalledTimes(1);
328+
329+ let call = callback.mock.calls[0];
330+
331+ expect(call).toHaveLength(enableSchedulerTracing ? 7 : 6);
332+ expect(call[0]).toBe('test');
333+ expect(call[1]).toBe('mount');
334+ expect(call[2]).toBe(10); // actual time
335+ expect(call[3]).toBe(10); // base time
336+ expect(call[4]).toBe(0); // start time
337+ expect(call[5]).toBe(10); // commit time
338+ expect(call[6]).toEqual(enableSchedulerTracing ? new Set() : undefined); // interaction events
339+
340+ callback.mockReset();
341+
342+ Scheduler.unstable_advanceTime(20); // 10 -> 30
343+
344+ // Updating a parent should report a re-render,
345+ // since React technically did a little bit of work between the Profiler and the bailed out subtree.
346+ renderer.update(<App />);
347+
348+ expect(callback).toHaveBeenCalledTimes(1);
349+
350+ call = callback.mock.calls[0];
351+
352+ expect(call).toHaveLength(enableSchedulerTracing ? 7 : 6);
353+ expect(call[0]).toBe('test');
354+ expect(call[1]).toBe('update');
355+ expect(call[2]).toBe(0); // actual time
356+ expect(call[3]).toBe(10); // base time
357+ expect(call[4]).toBe(30); // start time
358+ expect(call[5]).toBe(30); // commit time
359+ expect(call[6]).toEqual(enableSchedulerTracing ? new Set() : undefined); // interaction events
360+
361+ callback.mockReset();
362+
363+ Scheduler.unstable_advanceTime(20); // 30 -> 50
364+
365+ // Updating a sibling should not report a re-render.
366+ ReactTestRenderer.act(updateProfilerSibling);
367+
368+ expect(callback).not.toHaveBeenCalled();
369+ });
370+
298371 it('logs render times for both mount and update', () => {
299372 const callback = jest.fn();
300373
@@ -372,15 +445,15 @@ describe('Profiler', () => {
372445 Scheduler.unstable_advanceTime(5); // 0 -> 5
373446
374447 ReactTestRenderer.create(
375- <>
448+ <React.Fragment >
376449 <React.Profiler id="parent" onRender={callback}>
377450 <AdvanceTime byAmount={10}>
378451 <React.Profiler id="child" onRender={callback}>
379452 <AdvanceTime byAmount={20} />
380453 </React.Profiler>
381454 </AdvanceTime>
382455 </React.Profiler>
383- </>,
456+ </React.Fragment >,
384457 );
385458
386459 expect(callback).toHaveBeenCalledTimes(2);
@@ -407,14 +480,14 @@ describe('Profiler', () => {
407480 Scheduler.unstable_advanceTime(5); // 0 -> 5
408481
409482 ReactTestRenderer.create(
410- <>
483+ <React.Fragment >
411484 <React.Profiler id="first" onRender={callback}>
412485 <AdvanceTime byAmount={20} />
413486 </React.Profiler>
414487 <React.Profiler id="second" onRender={callback}>
415488 <AdvanceTime byAmount={5} />
416489 </React.Profiler>
417- </>,
490+ </React.Fragment >,
418491 );
419492
420493 expect(callback).toHaveBeenCalledTimes(2);
@@ -440,13 +513,13 @@ describe('Profiler', () => {
440513 Scheduler.unstable_advanceTime(5); // 0 -> 5
441514
442515 ReactTestRenderer.create(
443- <>
516+ <React.Fragment >
444517 <AdvanceTime byAmount={20} />
445518 <React.Profiler id="test" onRender={callback}>
446519 <AdvanceTime byAmount={5} />
447520 </React.Profiler>
448521 <AdvanceTime byAmount={20} />
449- </>,
522+ </React.Fragment >,
450523 );
451524
452525 expect(callback).toHaveBeenCalledTimes(1);
@@ -471,28 +544,18 @@ describe('Profiler', () => {
471544 }
472545 }
473546
474- class Pure extends React.PureComponent {
475- render() {
476- return this.props.children;
477- }
478- }
479-
480547 const renderer = ReactTestRenderer.create(
481548 <React.Profiler id="outer" onRender={callback}>
482549 <Updater>
483- <React.Profiler id="middle" onRender={callback}>
484- <Pure>
485- <React.Profiler id="inner" onRender={callback}>
486- <div />
487- </React.Profiler>
488- </Pure>
550+ <React.Profiler id="inner" onRender={callback}>
551+ <div />
489552 </React.Profiler>
490553 </Updater>
491554 </React.Profiler>,
492555 );
493556
494557 // All profile callbacks are called for initial render
495- expect(callback).toHaveBeenCalledTimes(3 );
558+ expect(callback).toHaveBeenCalledTimes(2 );
496559
497560 callback.mockReset();
498561
@@ -502,11 +565,11 @@ describe('Profiler', () => {
502565 });
503566 });
504567
505- // Only call profile updates for paths that have re-rendered
506- // Since "inner" is beneath a pure component, it isn 't called
507- expect(callback).toHaveBeenCalledTimes(2);
508- expect(callback.mock.calls[0][0]).toBe('middle' );
509- expect(callback.mock.calls[1 ][0]).toBe('outer');
568+ // Only call onRender for paths that have re-rendered.
569+ // Since the Updater's props didn 't change,
570+ // React does not re-render its children.
571+ expect(callback).toHaveBeenCalledTimes(1 );
572+ expect(callback.mock.calls[0 ][0]).toBe('outer');
510573 });
511574
512575 it('decreases actual time but not base time when sCU prevents an update', () => {
@@ -1455,11 +1518,11 @@ describe('Profiler', () => {
14551518 render() {
14561519 instance = this;
14571520 return (
1458- <>
1521+ <React.Fragment >
14591522 <Yield value="first" />
14601523 {this.state.count}
14611524 <Yield value="last" />
1462- </>
1525+ </React.Fragment >
14631526 );
14641527 }
14651528 }
0 commit comments