@samitouri / QOS-React / commits / 63cc7d2b31

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', () => {