@@ -2395,4 +2395,258 @@ describe('ReactIncremental', () => {
2395
2395
expect ( cduNextProps ) . toEqual ( [ { children : 'B' } ] ) ;
2396
2396
} ,
2397
2397
) ;
2398
+
2399
+ it ( 'updates descendants with new context values' , ( ) => {
2400
+ let rendered = [ ] ;
2401
+ let instance ;
2402
+
2403
+ class TopContextProvider extends React . Component {
2404
+ static childContextTypes = {
2405
+ count : PropTypes . number ,
2406
+ } ;
2407
+ constructor ( ) {
2408
+ super ( ) ;
2409
+ this . state = { count : 0 } ;
2410
+ instance = this ;
2411
+ }
2412
+ getChildContext = ( ) => ( {
2413
+ count : this . state . count ,
2414
+ } ) ;
2415
+ render = ( ) => this . props . children ;
2416
+ updateCount = ( ) =>
2417
+ this . setState ( state => ( {
2418
+ count : state . count + 1 ,
2419
+ } ) ) ;
2420
+ }
2421
+
2422
+ class Middle extends React . Component {
2423
+ render = ( ) => this . props . children ;
2424
+ }
2425
+
2426
+ class Child extends React . Component {
2427
+ static contextTypes = {
2428
+ count : PropTypes . number ,
2429
+ } ;
2430
+ render = ( ) => {
2431
+ rendered . push ( `count:${ this . context . count } ` ) ;
2432
+ return null ;
2433
+ } ;
2434
+ }
2435
+
2436
+ ReactNoop . render (
2437
+ < TopContextProvider > < Middle > < Child /> </ Middle > </ TopContextProvider > ,
2438
+ ) ;
2439
+
2440
+ ReactNoop . flush ( ) ;
2441
+ expect ( rendered ) . toEqual ( [ 'count:0' ] ) ;
2442
+ instance . updateCount ( ) ;
2443
+ ReactNoop . flush ( ) ;
2444
+ expect ( rendered ) . toEqual ( [ 'count:0' , 'count:1' ] ) ;
2445
+ } ) ;
2446
+
2447
+ it ( 'updates descendants with multiple context-providing ancestors with new context values' , ( ) => {
2448
+ let rendered = [ ] ;
2449
+ let instance ;
2450
+
2451
+ class TopContextProvider extends React . Component {
2452
+ static childContextTypes = {
2453
+ count : PropTypes . number ,
2454
+ } ;
2455
+ constructor ( ) {
2456
+ super ( ) ;
2457
+ this . state = { count : 0 } ;
2458
+ instance = this ;
2459
+ }
2460
+ getChildContext = ( ) => ( {
2461
+ count : this . state . count ,
2462
+ } ) ;
2463
+ render = ( ) => this . props . children ;
2464
+ updateCount = ( ) =>
2465
+ this . setState ( state => ( {
2466
+ count : state . count + 1 ,
2467
+ } ) ) ;
2468
+ }
2469
+
2470
+ class MiddleContextProvider extends React . Component {
2471
+ static childContextTypes = {
2472
+ name : PropTypes . string ,
2473
+ } ;
2474
+ getChildContext = ( ) => ( {
2475
+ name : 'brian' ,
2476
+ } ) ;
2477
+ render = ( ) => this . props . children ;
2478
+ }
2479
+
2480
+ class Child extends React . Component {
2481
+ static contextTypes = {
2482
+ count : PropTypes . number ,
2483
+ } ;
2484
+ render = ( ) => {
2485
+ rendered . push ( `count:${ this . context . count } ` ) ;
2486
+ return null ;
2487
+ } ;
2488
+ }
2489
+
2490
+ ReactNoop . render (
2491
+ < TopContextProvider >
2492
+ < MiddleContextProvider >
2493
+ < Child />
2494
+ </ MiddleContextProvider >
2495
+ </ TopContextProvider > ,
2496
+ ) ;
2497
+
2498
+ ReactNoop . flush ( ) ;
2499
+ expect ( rendered ) . toEqual ( [ 'count:0' ] ) ;
2500
+ instance . updateCount ( ) ;
2501
+ ReactNoop . flush ( ) ;
2502
+ expect ( rendered ) . toEqual ( [ 'count:0' , 'count:1' ] ) ;
2503
+ } ) ;
2504
+
2505
+ it ( 'should not update descendants with new context values if shouldComponentUpdate returns false' , ( ) => {
2506
+ let rendered = [ ] ;
2507
+ let instance ;
2508
+
2509
+ class TopContextProvider extends React . Component {
2510
+ static childContextTypes = {
2511
+ count : PropTypes . number ,
2512
+ } ;
2513
+ constructor ( ) {
2514
+ super ( ) ;
2515
+ this . state = { count : 0 } ;
2516
+ instance = this ;
2517
+ }
2518
+ getChildContext = ( ) => ( {
2519
+ count : this . state . count ,
2520
+ } ) ;
2521
+ render = ( ) => this . props . children ;
2522
+ updateCount = ( ) =>
2523
+ this . setState ( state => ( {
2524
+ count : state . count + 1 ,
2525
+ } ) ) ;
2526
+ }
2527
+
2528
+ class MiddleScu extends React . Component {
2529
+ shouldComponentUpdate ( ) {
2530
+ return false ;
2531
+ }
2532
+ render = ( ) => this . props . children ;
2533
+ }
2534
+
2535
+ class MiddleContextProvider extends React . Component {
2536
+ static childContextTypes = {
2537
+ name : PropTypes . string ,
2538
+ } ;
2539
+ getChildContext = ( ) => ( {
2540
+ name : 'brian' ,
2541
+ } ) ;
2542
+ render = ( ) => this . props . children ;
2543
+ }
2544
+
2545
+ class Child extends React . Component {
2546
+ static contextTypes = {
2547
+ count : PropTypes . number ,
2548
+ } ;
2549
+ render = ( ) => {
2550
+ rendered . push ( `count:${ this . context . count } ` ) ;
2551
+ return null ;
2552
+ } ;
2553
+ }
2554
+
2555
+ ReactNoop . render (
2556
+ < TopContextProvider >
2557
+ < MiddleScu >
2558
+ < MiddleContextProvider > < Child /> </ MiddleContextProvider >
2559
+ </ MiddleScu >
2560
+ </ TopContextProvider > ,
2561
+ ) ;
2562
+
2563
+ ReactNoop . flush ( ) ;
2564
+ expect ( rendered ) . toEqual ( [ 'count:0' ] ) ;
2565
+ instance . updateCount ( ) ;
2566
+ ReactNoop . flush ( ) ;
2567
+ expect ( rendered ) . toEqual ( [ 'count:0' ] ) ;
2568
+ } ) ;
2569
+
2570
+ it ( 'should update descendants with new context values if setState() is called in the middle of the tree' , ( ) => {
2571
+ let rendered = [ ] ;
2572
+ let middleInstance ;
2573
+ let topInstance ;
2574
+
2575
+ class TopContextProvider extends React . Component {
2576
+ static childContextTypes = {
2577
+ count : PropTypes . number ,
2578
+ } ;
2579
+ constructor ( ) {
2580
+ super ( ) ;
2581
+ this . state = { count : 0 } ;
2582
+ topInstance = this ;
2583
+ }
2584
+ getChildContext = ( ) => ( {
2585
+ count : this . state . count ,
2586
+ } ) ;
2587
+ render = ( ) => this . props . children ;
2588
+ updateCount = ( ) =>
2589
+ this . setState ( state => ( {
2590
+ count : state . count + 1 ,
2591
+ } ) ) ;
2592
+ }
2593
+
2594
+ class MiddleScu extends React . Component {
2595
+ shouldComponentUpdate ( ) {
2596
+ return false ;
2597
+ }
2598
+ render = ( ) => this . props . children ;
2599
+ }
2600
+
2601
+ class MiddleContextProvider extends React . Component {
2602
+ static childContextTypes = {
2603
+ name : PropTypes . string ,
2604
+ } ;
2605
+ constructor ( ) {
2606
+ super ( ) ;
2607
+ this . state = { name : 'brian' } ;
2608
+ middleInstance = this ;
2609
+ }
2610
+ getChildContext = ( ) => ( {
2611
+ name : this . state . name ,
2612
+ } ) ;
2613
+ updateName = name => {
2614
+ this . setState ( { name} ) ;
2615
+ } ;
2616
+ render = ( ) => this . props . children ;
2617
+ }
2618
+
2619
+ class Child extends React . Component {
2620
+ static contextTypes = {
2621
+ count : PropTypes . number ,
2622
+ name : PropTypes . string ,
2623
+ } ;
2624
+ render = ( ) => {
2625
+ rendered . push ( `count:${ this . context . count } , name:${ this . context . name } ` ) ;
2626
+ return null ;
2627
+ } ;
2628
+ }
2629
+
2630
+ ReactNoop . render (
2631
+ < TopContextProvider >
2632
+ < MiddleScu >
2633
+ < MiddleContextProvider >
2634
+ < Child />
2635
+ </ MiddleContextProvider >
2636
+ </ MiddleScu >
2637
+ </ TopContextProvider > ,
2638
+ ) ;
2639
+
2640
+ ReactNoop . flush ( ) ;
2641
+ expect ( rendered ) . toEqual ( [ 'count:0, name:brian' ] ) ;
2642
+ topInstance . updateCount ( ) ;
2643
+ ReactNoop . flush ( ) ;
2644
+ expect ( rendered ) . toEqual ( [ 'count:0, name:brian' ] ) ;
2645
+ middleInstance . updateName ( 'not brian' ) ;
2646
+ ReactNoop . flush ( ) ;
2647
+ expect ( rendered ) . toEqual ( [
2648
+ 'count:0, name:brian' ,
2649
+ 'count:1, name:not brian' ,
2650
+ ] ) ;
2651
+ } ) ;
2398
2652
} ) ;
0 commit comments