Test useContext in pure, forwardRef, and PureComponent
Dan Abramov committed
Oct 15, 2018 at 17:20 UTC
63cc7d2b31b4e5ad17c07b383a328c598c91276e
1 file changed
+59
-38
packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js
+59
-38
@@ -57,6 +57,25 @@ describe('ReactNewContext', () => {
57
return render(contextValue);
58
},
59
);
60
+ sharedContextTests('useContext inside forwardRef component', Context =>
61
+ React.forwardRef(function Consumer(props, ref) {
62
+ const observedBits = props.unstable_observedBits;
63
+ const contextValue = useContext(Context, observedBits);
64
+ const render = props.children;
65
+ return render(contextValue);
66
+ }),
67
+ );
68
+ sharedContextTests(
69
+ 'useContext inside memoized function component',
70
+ Context =>
71
+ React.memo(function Consumer(props) {
72
+ const observedBits = props.unstable_observedBits;
73
+ const contextValue = useContext(Context, observedBits);
74
+ const render = props.children;
75
+ return render(contextValue);
76
+ }),
77
+ true,
78
+ );
79
sharedContextTests(
80
'readContext(Context) inside class component',
81
Context =>
@@ -70,7 +89,7 @@ describe('ReactNewContext', () => {
89
},
90
);
91
73
- function sharedContextTests(label, getConsumer) {
92
+ function sharedContextTests(label, getConsumer, isPure) {
93
describe(`reading context with ${label}`, () => {
94
it('simple mount and update', () => {
95
const Context = React.createContext(1);
@@ -855,46 +874,48 @@ describe('ReactNewContext', () => {
874
expect(ReactNoop.getChildren()).toEqual([span(2), span(2)]);
875
});
876
858
- // Context consumer bails out on propagating "deep" updates when `value` hasn't changed.
859
- // However, it doesn't bail out from rendering if the component above it re-rendered anyway.
860
- // If we bailed out on referential equality, it would be confusing that you
861
- // can call this.setState(), but an autobound render callback "blocked" the update.
862
- // https://github.com/facebook/react/pull/12470#issuecomment-376917711
863
- it('consumer does not bail out if there were no bailouts above it', () => {
864
- const Context = React.createContext(0);
865
- const Consumer = getConsumer(Context);
866
-
867
- class App extends React.Component {
868
- state = {
869
- text: 'hello',
870
- };
871
-
872
- renderConsumer = context => {
873
- ReactNoop.yield('App#renderConsumer');
874
- return <span prop={this.state.text} />;
875
- };
876
-
877
- render() {
878
- ReactNoop.yield('App');
879
- return (
880
- <Context.Provider value={this.props.value}>
881
- <Consumer>{this.renderConsumer}</Consumer>
882
- </Context.Provider>
883
- );
877
+ if (!isPure) {
878
+ // Context consumer bails out on propagating "deep" updates when `value` hasn't changed.
879
+ // However, it doesn't bail out from rendering if the component above it re-rendered anyway.
880
+ // If we bailed out on referential equality, it would be confusing that you
881
+ // can call this.setState(), but an autobound render callback "blocked" the update.
882
+ // https://github.com/facebook/react/pull/12470#issuecomment-376917711
883
+ it('consumer does not bail out if there were no bailouts above it', () => {
884
+ const Context = React.createContext(0);
885
+ const Consumer = getConsumer(Context);
886
+
887
+ class App extends React.Component {
888
+ state = {
889
+ text: 'hello',
890
+ };
891
+
892
+ renderConsumer = context => {
893
+ ReactNoop.yield('App#renderConsumer');
894
+ return <span prop={this.state.text} />;
895
+ };
896
+
897
+ render() {
898
+ ReactNoop.yield('App');
899
+ return (
900
+ <Context.Provider value={this.props.value}>
901
+ <Consumer>{this.renderConsumer}</Consumer>
902
+ </Context.Provider>
903
+ );
904
+ }
905
}
885
- }
906
887
- // Initial mount
888
- let inst;
889
- ReactNoop.render(<App value={1} ref={ref => (inst = ref)} />);
890
- expect(ReactNoop.flush()).toEqual(['App', 'App#renderConsumer']);
891
- expect(ReactNoop.getChildren()).toEqual([span('hello')]);
907
+ // Initial mount
908
+ let inst;
909
+ ReactNoop.render(<App value={1} ref={ref => (inst = ref)} />);
910
+ expect(ReactNoop.flush()).toEqual(['App', 'App#renderConsumer']);
911
+ expect(ReactNoop.getChildren()).toEqual([span('hello')]);
912
893
- // Update
894
- inst.setState({text: 'goodbye'});
895
- expect(ReactNoop.flush()).toEqual(['App', 'App#renderConsumer']);
896
- expect(ReactNoop.getChildren()).toEqual([span('goodbye')]);
897
- });
913
+ // Update
914
+ inst.setState({text: 'goodbye'});
915
+ expect(ReactNoop.flush()).toEqual(['App', 'App#renderConsumer']);
916
+ expect(ReactNoop.getChildren()).toEqual([span('goodbye')]);
917
+ });
918
+ }
919
920
// This is a regression case for https://github.com/facebook/react/issues/12389.
921
it('does not run into an infinite loop', () => {