Browse Source

Official redux support (#3675)

* the people have spoken

* support for projects without redux
Daniel Zlotin 6 years ago
parent
commit
967d7bf556
No account linked to committer's email address

+ 8
- 0
lib/src/Navigation.ts View File

@@ -56,6 +56,14 @@ export class Navigation {
56 56
     return this.componentRegistry.registerComponent(componentName, getComponentClassFunc);
57 57
   }
58 58
 
59
+  /**
60
+   * Utility helper function like registerComponent,
61
+   * wraps the provided component with a react-redux Provider with the passed redux store
62
+   */
63
+  public registerComponentWithRedux(componentName: string, getComponentClassFunc: ComponentProvider, ReduxProvider: any, reduxStore: any): ComponentType<any> {
64
+    return this.componentRegistry.registerComponent(componentName, getComponentClassFunc, ReduxProvider, reduxStore);
65
+  }
66
+
59 67
   /**
60 68
    * Reset the app to a new layout
61 69
    */

+ 2
- 2
lib/src/components/ComponentRegistry.ts View File

@@ -7,9 +7,9 @@ import { ComponentEventsObserver } from '../events/ComponentEventsObserver';
7 7
 export class ComponentRegistry {
8 8
   constructor(private readonly store: Store, private readonly componentEventsObserver: ComponentEventsObserver) { }
9 9
 
10
-  registerComponent(componentName: string, getComponentClassFunc: ComponentProvider): ComponentType<any> {
10
+  registerComponent(componentName: string, getComponentClassFunc: ComponentProvider, ReduxProvider?: any, userStore?: any): ComponentType<any> {
11 11
     const OriginalComponentClass = getComponentClassFunc();
12
-    const NavigationComponent = ComponentWrapper.wrap(componentName, OriginalComponentClass, this.store, this.componentEventsObserver);
12
+    const NavigationComponent = ComponentWrapper.wrap(componentName, OriginalComponentClass, this.store, this.componentEventsObserver, ReduxProvider, userStore);
13 13
     this.store.setOriginalComponentClassForName(componentName, OriginalComponentClass);
14 14
     AppRegistry.registerComponent(componentName, () => NavigationComponent);
15 15
     return NavigationComponent;

+ 29
- 0
lib/src/components/ComponentWrapper.test.tsx View File

@@ -134,4 +134,33 @@ describe('ComponentWrapper', () => {
134 134
     tree.unmount();
135 135
     expect(componentEventsObserver.unmounted).toHaveBeenCalledTimes(1);
136 136
   });
137
+
138
+  describe(`register with redux store`, () => {
139
+    class MyReduxComp extends React.Component<any> {
140
+      static get options() {
141
+        return { foo: 123 };
142
+      }
143
+      render() {
144
+        return (
145
+          <Text>{this.props.txt}</Text>
146
+        );
147
+      }
148
+    }
149
+    function mapStateToProps(state) {
150
+      return {
151
+        txt: state.txt
152
+      };
153
+    }
154
+    const ConnectedComp = require('react-redux').connect(mapStateToProps)(MyReduxComp);
155
+    const ReduxProvider = require('react-redux').Provider;
156
+    const initialState = { txt: 'it just works' };
157
+    const reduxStore = require('redux').createStore((state = initialState) => state);
158
+
159
+    it(`wraps the component with a react-redux provider with passed store`, () => {
160
+      const NavigationComponent = ComponentWrapper.wrap(componentName, ConnectedComp, store, componentEventsObserver, ReduxProvider, reduxStore);
161
+      const tree = renderer.create(<NavigationComponent componentId={'theCompId'} />);
162
+      expect(tree.toJSON()!.children).toEqual(['it just works']);
163
+      expect((NavigationComponent as any).options).toEqual({ foo: 123 });
164
+    });
165
+  });
137 166
 });

+ 23
- 2
lib/src/components/ComponentWrapper.tsx View File

@@ -8,7 +8,9 @@ export class ComponentWrapper {
8 8
     componentName: string,
9 9
     OriginalComponentClass: React.ComponentType<any>,
10 10
     store,
11
-    componentEventsObserver): React.ComponentType<any> {
11
+    componentEventsObserver,
12
+    ReduxProvider?,
13
+    reduxStore?): React.ComponentType<any> {
12 14
 
13 15
     class WrappedComponent extends React.Component<any, { componentId: string; allProps: {}; }> {
14 16
 
@@ -51,6 +53,25 @@ export class ComponentWrapper {
51 53
 
52 54
     ReactLifecyclesCompat.polyfill(WrappedComponent);
53 55
     require('hoist-non-react-statics')(WrappedComponent, OriginalComponentClass);
54
-    return WrappedComponent;
56
+
57
+    if (reduxStore) {
58
+      return ComponentWrapper.wrapWithRedux(WrappedComponent, ReduxProvider, reduxStore);
59
+    } else {
60
+      return WrappedComponent;
61
+    }
62
+  }
63
+
64
+  static wrapWithRedux(WrappedComponent, ReduxProvider, reduxStore): React.ComponentType<any> {
65
+    class ReduxWrapper extends React.Component<any, any> {
66
+      render() {
67
+        return (
68
+          <ReduxProvider store={reduxStore}>
69
+            <WrappedComponent {...this.props} />
70
+          </ReduxProvider>
71
+        );
72
+      }
73
+    }
74
+    require('hoist-non-react-statics')(ReduxWrapper, WrappedComponent);
75
+    return ReduxWrapper;
55 76
   }
56 77
 }