Kaynağa Gözat

Remove duplication

The files react/index.native.js and react/index.web.js ended up having
very similar source code related to initializing the Redux store. Remove
the duplication.

Additionally, I always wanted the App React Component to be consumed
without the need to provide a Redux store to it.
j8
Lyubomir Marinov 8 yıl önce
ebeveyn
işleme
49b3b49f3e

+ 112
- 6
react/features/app/components/AbstractApp.js Dosyayı Görüntüle

@@ -1,11 +1,14 @@
1 1
 import React, { Component } from 'react';
2 2
 import { Provider } from 'react-redux';
3
+import { compose, createStore } from 'redux';
4
+import Thunk from 'redux-thunk';
3 5
 
4 6
 import { RouteRegistry } from '../../base/navigator';
5 7
 import {
6 8
     localParticipantJoined,
7 9
     localParticipantLeft
8 10
 } from '../../base/participants';
11
+import { MiddlewareRegistry, ReducerRegistry } from '../../base/redux';
9 12
 
10 13
 import {
11 14
     appNavigate,
@@ -45,11 +48,18 @@ export class AbstractApp extends Component {
45 48
 
46 49
         this.state = {
47 50
             /**
48
-             * The Route rendered by this App.
51
+             * The Route rendered by this AbstractApp.
49 52
              *
50 53
              * @type {Route}
51 54
              */
52
-            route: undefined
55
+            route: undefined,
56
+
57
+            /**
58
+             * The Redux store used by this AbstractApp.
59
+             *
60
+             * @type {Store}
61
+             */
62
+            store: this._maybeCreateStore(props)
53 63
         };
54 64
     }
55 65
 
@@ -60,7 +70,7 @@ export class AbstractApp extends Component {
60 70
      * @inheritdoc
61 71
      */
62 72
     componentWillMount() {
63
-        const dispatch = this.props.store.dispatch;
73
+        const dispatch = this._getStore().dispatch;
64 74
 
65 75
         dispatch(appWillMount(this));
66 76
 
@@ -69,6 +79,32 @@ export class AbstractApp extends Component {
69 79
         this._openURL(this._getDefaultURL());
70 80
     }
71 81
 
82
+    /**
83
+     * Notifies this mounted React Component that it will receive new props.
84
+     * Makes sure that this AbstractApp has a Redux store to use.
85
+     *
86
+     * @inheritdoc
87
+     * @param {Object} nextProps - The read-only React Component props that this
88
+     * instance will receive.
89
+     * @returns {void}
90
+     */
91
+    componentWillReceiveProps(nextProps) {
92
+        // The consumer of this AbstractApp did not provide a Redux store.
93
+        if (typeof nextProps.store === 'undefined'
94
+
95
+                // The consumer of this AbstractApp  did provide a Redux store
96
+                // before. Which means that the consumer changed their mind. In
97
+                // such a case this instance should create its own internal
98
+                // Redux store. If the consumer did not provide a Redux store
99
+                // before, then this instance is using its own internal Redux
100
+                // store already.
101
+                && typeof this.props.store !== 'undefined') {
102
+            this.setState({
103
+                store: this._maybeCreateStore(nextProps)
104
+            });
105
+        }
106
+    }
107
+
72 108
     /**
73 109
      * Dispose lib-jitsi-meet and remove local participant when component is
74 110
      * going to be unmounted.
@@ -76,7 +112,7 @@ export class AbstractApp extends Component {
76 112
      * @inheritdoc
77 113
      */
78 114
     componentWillUnmount() {
79
-        const dispatch = this.props.store.dispatch;
115
+        const dispatch = this._getStore().dispatch;
80 116
 
81 117
         dispatch(localParticipantLeft());
82 118
 
@@ -94,7 +130,7 @@ export class AbstractApp extends Component {
94 130
 
95 131
         if (route) {
96 132
             return (
97
-                <Provider store = { this.props.store }>
133
+                <Provider store = { this._getStore() }>
98 134
                     {
99 135
                         this._createElement(route.component)
100 136
                     }
@@ -142,6 +178,36 @@ export class AbstractApp extends Component {
142 178
         return React.createElement(component, { ...thisProps, ...props });
143 179
     }
144 180
 
181
+    /**
182
+     * Initializes a new Redux store instance suitable for use by
183
+     * this AbstractApp.
184
+     *
185
+     * @private
186
+     * @returns {Store} - A new Redux store instance suitable for use by
187
+     * this AbstractApp.
188
+     */
189
+    _createStore() {
190
+        // Create combined reducer from all reducers in ReducerRegistry.
191
+        const reducer = ReducerRegistry.combineReducers();
192
+
193
+        // Apply all registered middleware from the MiddlewareRegistry and
194
+        // additional 3rd party middleware:
195
+        // - Thunk - allows us to dispatch async actions easily. For more info
196
+        // @see https://github.com/gaearon/redux-thunk.
197
+        let middleware = MiddlewareRegistry.applyMiddleware(Thunk);
198
+
199
+        // Try to enable Redux DevTools Chrome extension in order to make it
200
+        // available for the purposes of facilitating development.
201
+        let devToolsExtension;
202
+
203
+        if (typeof window === 'object'
204
+                && (devToolsExtension = window.devToolsExtension)) {
205
+            middleware = compose(middleware, devToolsExtension());
206
+        }
207
+
208
+        return createStore(reducer, middleware);
209
+    }
210
+
145 211
     /**
146 212
      * Gets the default URL to be opened when this App mounts.
147 213
      *
@@ -189,6 +255,22 @@ export class AbstractApp extends Component {
189 255
         return 'https://meet.jit.si';
190 256
     }
191 257
 
258
+    /**
259
+     * Gets the Redux store used by this AbstractApp.
260
+     *
261
+     * @protected
262
+     * @returns {Store} - The Redux store used by this AbstractApp.
263
+     */
264
+    _getStore() {
265
+        let store = this.state.store;
266
+
267
+        if (typeof store === 'undefined') {
268
+            store = this.props.store;
269
+        }
270
+
271
+        return store;
272
+    }
273
+
192 274
     /**
193 275
      * Gets a Location object from the window with information about the current
194 276
      * location of the document. Explicitly defined to allow extenders to
@@ -204,6 +286,30 @@ export class AbstractApp extends Component {
204 286
         return undefined;
205 287
     }
206 288
 
289
+    /**
290
+     * Creates a Redux store to be used by this AbstractApp if such as store is
291
+     * not defined by the consumer of this AbstractApp through its
292
+     * read-only React Component props.
293
+     *
294
+     * @param {Object} props - The read-only React Component props that will
295
+     * eventually be received by this AbstractApp.
296
+     * @private
297
+     * @returns {Store} - The Redux store to be used by this AbstractApp.
298
+     */
299
+    _maybeCreateStore(props) {
300
+        // The application Jitsi Meet is architected with Redux. However, I do
301
+        // not want consumers of the App React Component to be forced into
302
+        // dealing with Redux. If the consumer did not provide an external Redux
303
+        // store, utilize an internal Redux store.
304
+        let store = props.store;
305
+
306
+        if (typeof store === 'undefined') {
307
+            store = this._createStore();
308
+        }
309
+
310
+        return store;
311
+    }
312
+
207 313
     /**
208 314
      * Navigates to a specific Route.
209 315
      *
@@ -269,6 +375,6 @@ export class AbstractApp extends Component {
269 375
      * @returns {void}
270 376
      */
271 377
     _openURL(url) {
272
-        this.props.store.dispatch(appNavigate(url));
378
+        this._getStore().dispatch(appNavigate(url));
273 379
     }
274 380
 }

+ 2
- 2
react/features/app/components/App.web.js Dosyayı Görüntüle

@@ -22,7 +22,7 @@ export class App extends AbstractApp {
22 22
     componentWillMount(...args) {
23 23
         super.componentWillMount(...args);
24 24
 
25
-        this.props.store.dispatch(appInit());
25
+        this._getStore().dispatch(appInit());
26 26
     }
27 27
 
28 28
     /**
@@ -44,7 +44,7 @@ export class App extends AbstractApp {
44 44
      */
45 45
     _navigate(route) {
46 46
         let path = route.path;
47
-        const store = this.props.store;
47
+        const store = this._getStore();
48 48
 
49 49
         // The syntax :room bellow is defined by react-router. It "matches a URL
50 50
         // segment up to the next /, ?, or #. The matched string is called a

+ 0
- 19
react/index.native.js Dosyayı Görüntüle

@@ -1,26 +1,8 @@
1 1
 import React, { Component } from 'react';
2 2
 import { AppRegistry, Linking } from 'react-native';
3
-import { createStore } from 'redux';
4
-import Thunk from 'redux-thunk';
5 3
 
6 4
 import config from './config';
7 5
 import { App } from './features/app';
8
-import {
9
-    MiddlewareRegistry,
10
-    ReducerRegistry
11
-} from './features/base/redux';
12
-
13
-// Create combined reducer from all reducers in registry.
14
-const reducer = ReducerRegistry.combineReducers();
15
-
16
-// Apply all registered middleware from the MiddlewareRegistry + additional
17
-// 3rd party middleware:
18
-// - Thunk - allows us to dispatch async actions easily. For more info
19
-// @see https://github.com/gaearon/redux-thunk.
20
-const middleware = MiddlewareRegistry.applyMiddleware(Thunk);
21
-
22
-// Create Redux store with our reducer and middleware.
23
-const store = createStore(reducer, middleware);
24 6
 
25 7
 /**
26 8
  * React Native doesn't support specifying props to the main/root component (in
@@ -83,7 +65,6 @@ class Root extends Component {
83 65
         return (
84 66
             <App
85 67
                 config = { config }
86
-                store = { store }
87 68
                 url = { this.state.url } />
88 69
         );
89 70
     }

+ 1
- 27
react/index.web.js Dosyayı Görüntüle

@@ -2,36 +2,12 @@
2 2
 
3 3
 import React from 'react';
4 4
 import ReactDOM from 'react-dom';
5
-import { compose, createStore } from 'redux';
6
-import Thunk from 'redux-thunk';
7 5
 
8 6
 import config from './config';
9 7
 import { App } from './features/app';
10
-import { MiddlewareRegistry, ReducerRegistry } from './features/base/redux';
11 8
 
12 9
 const logger = require('jitsi-meet-logger').getLogger(__filename);
13 10
 
14
-// Create combined reducer from all reducers in registry.
15
-const reducer = ReducerRegistry.combineReducers();
16
-
17
-// Apply all registered middleware from the MiddlewareRegistry + additional
18
-// 3rd party middleware:
19
-// - Thunk - allows us to dispatch async actions easily. For more info
20
-// @see https://github.com/gaearon/redux-thunk.
21
-let middleware = MiddlewareRegistry.applyMiddleware(Thunk);
22
-
23
-// Try to enable Redux DevTools Chrome extension in order to make it available
24
-// for the purposes of facilitating development.
25
-let devToolsExtension;
26
-
27
-if (typeof window === 'object'
28
-        && (devToolsExtension = window.devToolsExtension)) {
29
-    middleware = compose(middleware, devToolsExtension());
30
-}
31
-
32
-// Create Redux store with our reducer and middleware.
33
-const store = createStore(reducer, middleware);
34
-
35 11
 /**
36 12
  * Renders the app when the DOM tree has been loaded.
37 13
  */
@@ -43,9 +19,7 @@ document.addEventListener('DOMContentLoaded', () => {
43 19
 
44 20
     // Render the main Component.
45 21
     ReactDOM.render(
46
-        <App
47
-            config = { config }
48
-            store = { store } />,
22
+        <App config = { config } />,
49 23
         document.getElementById('react'));
50 24
 });
51 25
 

Loading…
İptal
Kaydet