@@ -613,8 +613,114 @@ describe('ReactDOMServerHooks', () => {
613
613
} ) ;
614
614
615
615
describe ( 'useContext' , ( ) => {
616
+ itThrowsWhenRendering (
617
+ 'if used inside a class component' ,
618
+ async render => {
619
+ const Context = React . createContext ( { } , ( ) => { } ) ;
620
+ class Counter extends React . Component {
621
+ render ( ) {
622
+ let [ count ] = useContext ( Context ) ;
623
+ return < Text text = { count } /> ;
624
+ }
625
+ }
626
+
627
+ return render ( < Counter /> ) ;
628
+ } ,
629
+ 'Hooks can only be called inside the body of a function component.' ,
630
+ ) ;
631
+ } ) ;
632
+
633
+ itRenders (
634
+ 'can use the same context multiple times in the same function' ,
635
+ async render => {
636
+ const Context = React . createContext ( { foo : 0 , bar : 0 , baz : 0 } ) ;
637
+
638
+ function Provider ( props ) {
639
+ return (
640
+ < Context . Provider
641
+ value = { { foo : props . foo , bar : props . bar , baz : props . baz } } >
642
+ { props . children }
643
+ </ Context . Provider >
644
+ ) ;
645
+ }
646
+
647
+ function FooAndBar ( ) {
648
+ const { foo} = useContext ( Context ) ;
649
+ const { bar} = useContext ( Context ) ;
650
+ return < Text text = { `Foo: ${ foo } , Bar: ${ bar } ` } /> ;
651
+ }
652
+
653
+ function Baz ( ) {
654
+ const { baz} = useContext ( Context ) ;
655
+ return < Text text = { 'Baz: ' + baz } /> ;
656
+ }
657
+
658
+ class Indirection extends React . Component {
659
+ render ( ) {
660
+ return this . props . children ;
661
+ }
662
+ }
663
+
664
+ function App ( props ) {
665
+ return (
666
+ < div >
667
+ < Provider foo = { props . foo } bar = { props . bar } baz = { props . baz } >
668
+ < Indirection >
669
+ < Indirection >
670
+ < FooAndBar />
671
+ </ Indirection >
672
+ < Indirection >
673
+ < Baz />
674
+ </ Indirection >
675
+ </ Indirection >
676
+ </ Provider >
677
+ </ div >
678
+ ) ;
679
+ }
680
+
681
+ const domNode = await render ( < App foo = { 1 } bar = { 3 } baz = { 5 } /> ) ;
682
+ expect ( clearYields ( ) ) . toEqual ( [ 'Foo: 1, Bar: 3' , 'Baz: 5' ] ) ;
683
+ expect ( domNode . childNodes . length ) . toBe ( 2 ) ;
684
+ expect ( domNode . firstChild . tagName ) . toEqual ( 'SPAN' ) ;
685
+ expect ( domNode . firstChild . textContent ) . toEqual ( 'Foo: 1, Bar: 3' ) ;
686
+ expect ( domNode . lastChild . tagName ) . toEqual ( 'SPAN' ) ;
687
+ expect ( domNode . lastChild . textContent ) . toEqual ( 'Baz: 5' ) ;
688
+ } ,
689
+ ) ;
690
+
691
+ itRenders ( 'warns when bitmask is passed to useContext' , async render => {
692
+ let Context = React . createContext ( 'Hi' ) ;
693
+
694
+ function Foo ( ) {
695
+ return < span > { useContext ( Context , 1 ) } </ span > ;
696
+ }
697
+
698
+ const domNode = await render ( < Foo /> , 1 ) ;
699
+ expect ( domNode . textContent ) . toBe ( 'Hi' ) ;
700
+ } ) ;
701
+
702
+ describe ( 'useDebugValue' , ( ) => {
703
+ itRenders ( 'is a noop' , async render => {
704
+ function Counter ( props ) {
705
+ const debugValue = useDebugValue ( 123 ) ;
706
+ return < Text text = { typeof debugValue } /> ;
707
+ }
708
+
709
+ const domNode = await render ( < Counter /> ) ;
710
+ expect ( domNode . textContent ) . toEqual ( 'undefined' ) ;
711
+ } ) ;
712
+ } ) ;
713
+
714
+ describe ( 'readContext' , ( ) => {
715
+ function readContext ( Context , observedBits ) {
716
+ const dispatcher =
717
+ React . __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
718
+ . ReactCurrentDispatcher . current ;
719
+ return dispatcher . readContext ( Context , observedBits ) ;
720
+ }
721
+
616
722
itRenders (
617
- 'can use the same context multiple times in the same function' ,
723
+ 'can read the same context multiple times in the same function' ,
618
724
async render => {
619
725
const Context = React . createContext (
620
726
{ foo : 0 , bar : 0 , baz : 0 } ,
@@ -643,13 +749,13 @@ describe('ReactDOMServerHooks', () => {
643
749
}
644
750
645
751
function FooAndBar ( ) {
646
- const { foo} = useContext ( Context , 0b001 ) ;
647
- const { bar} = useContext ( Context , 0b010 ) ;
752
+ const { foo} = readContext ( Context , 0b001 ) ;
753
+ const { bar} = readContext ( Context , 0b010 ) ;
648
754
return < Text text = { `Foo: ${ foo } , Bar: ${ bar } ` } /> ;
649
755
}
650
756
651
757
function Baz ( ) {
652
- const { baz} = useContext ( Context , 0b100 ) ;
758
+ const { baz} = readContext ( Context , 0b100 ) ;
653
759
return < Text text = { 'Baz: ' + baz } /> ;
654
760
}
655
761
@@ -689,43 +795,6 @@ describe('ReactDOMServerHooks', () => {
689
795
} ,
690
796
) ;
691
797
692
- itThrowsWhenRendering (
693
- 'if used inside a class component' ,
694
- async render => {
695
- const Context = React . createContext ( { } , ( ) => { } ) ;
696
- class Counter extends React . Component {
697
- render ( ) {
698
- let [ count ] = useContext ( Context ) ;
699
- return < Text text = { count } /> ;
700
- }
701
- }
702
-
703
- return render ( < Counter /> ) ;
704
- } ,
705
- 'Hooks can only be called inside the body of a function component.' ,
706
- ) ;
707
- } ) ;
708
-
709
- describe ( 'useDebugValue' , ( ) => {
710
- itRenders ( 'is a noop' , async render => {
711
- function Counter ( props ) {
712
- const debugValue = useDebugValue ( 123 ) ;
713
- return < Text text = { typeof debugValue } /> ;
714
- }
715
-
716
- const domNode = await render ( < Counter /> ) ;
717
- expect ( domNode . textContent ) . toEqual ( 'undefined' ) ;
718
- } ) ;
719
- } ) ;
720
-
721
- describe ( 'readContext' , ( ) => {
722
- function readContext ( Context , observedBits ) {
723
- const dispatcher =
724
- React . __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
725
- . ReactCurrentDispatcher . current ;
726
- return dispatcher . readContext ( Context , observedBits ) ;
727
- }
728
-
729
798
itRenders ( 'with a warning inside useMemo and useReducer' , async render => {
730
799
const Context = React . createContext ( 42 ) ;
731
800
0 commit comments