|
1 | | -import React, { Component } from 'react'; |
2 | | -import storeShape from '../utils/storeShape'; |
3 | | -import shallowEqual from '../utils/shallowEqual'; |
4 | | -import isPlainObject from '../utils/isPlainObject'; |
5 | | -import wrapActionCreators from '../utils/wrapActionCreators'; |
6 | | -import hoistStatics from 'hoist-non-react-statics'; |
7 | | -import invariant from 'invariant'; |
8 | | - |
9 | | -const defaultMapStateToProps = () => ({}); |
10 | | -const defaultMapDispatchToProps = dispatch => ({ dispatch }); |
| 1 | +import React, { Component } from 'react' |
| 2 | +import storeShape from '../utils/storeShape' |
| 3 | +import shallowEqual from '../utils/shallowEqual' |
| 4 | +import isPlainObject from '../utils/isPlainObject' |
| 5 | +import wrapActionCreators from '../utils/wrapActionCreators' |
| 6 | +import hoistStatics from 'hoist-non-react-statics' |
| 7 | +import invariant from 'invariant' |
| 8 | + |
| 9 | +const defaultMapStateToProps = () => ({}) |
| 10 | +const defaultMapDispatchToProps = dispatch => ({ dispatch }) |
11 | 11 | const defaultMergeProps = (stateProps, dispatchProps, parentProps) => ({ |
12 | 12 | ...parentProps, |
13 | 13 | ...stateProps, |
14 | 14 | ...dispatchProps |
15 | | -}); |
| 15 | +}) |
16 | 16 |
|
17 | 17 | function getDisplayName(WrappedComponent) { |
18 | | - return WrappedComponent.displayName || WrappedComponent.name || 'Component'; |
| 18 | + return WrappedComponent.displayName || WrappedComponent.name || 'Component' |
19 | 19 | } |
20 | 20 |
|
21 | 21 | // Helps track hot reloading. |
22 | | -let nextVersion = 0; |
| 22 | +let nextVersion = 0 |
23 | 23 |
|
24 | 24 | export default function connect(mapStateToProps, mapDispatchToProps, mergeProps, options = {}) { |
25 | | - const shouldSubscribe = Boolean(mapStateToProps); |
26 | | - const finalMapStateToProps = mapStateToProps || defaultMapStateToProps; |
| 25 | + const shouldSubscribe = Boolean(mapStateToProps) |
| 26 | + const finalMapStateToProps = mapStateToProps || defaultMapStateToProps |
27 | 27 | const finalMapDispatchToProps = isPlainObject(mapDispatchToProps) ? |
28 | 28 | wrapActionCreators(mapDispatchToProps) : |
29 | | - mapDispatchToProps || defaultMapDispatchToProps; |
30 | | - const finalMergeProps = mergeProps || defaultMergeProps; |
31 | | - const shouldUpdateStateProps = finalMapStateToProps.length > 1; |
32 | | - const shouldUpdateDispatchProps = finalMapDispatchToProps.length > 1; |
33 | | - const { pure = true, withRef = false } = options; |
| 29 | + mapDispatchToProps || defaultMapDispatchToProps |
| 30 | + const finalMergeProps = mergeProps || defaultMergeProps |
| 31 | + const shouldUpdateStateProps = finalMapStateToProps.length > 1 |
| 32 | + const shouldUpdateDispatchProps = finalMapDispatchToProps.length > 1 |
| 33 | + const { pure = true, withRef = false } = options |
34 | 34 |
|
35 | 35 | // Helps track hot reloading. |
36 | | - const version = nextVersion++; |
| 36 | + const version = nextVersion++ |
37 | 37 |
|
38 | 38 | function computeStateProps(store, props) { |
39 | | - const state = store.getState(); |
| 39 | + const state = store.getState() |
40 | 40 | const stateProps = shouldUpdateStateProps ? |
41 | 41 | finalMapStateToProps(state, props) : |
42 | | - finalMapStateToProps(state); |
| 42 | + finalMapStateToProps(state) |
43 | 43 |
|
44 | 44 | invariant( |
45 | 45 | isPlainObject(stateProps), |
46 | 46 | '`mapStateToProps` must return an object. Instead received %s.', |
47 | 47 | stateProps |
48 | | - ); |
49 | | - return stateProps; |
| 48 | + ) |
| 49 | + return stateProps |
50 | 50 | } |
51 | 51 |
|
52 | 52 | function computeDispatchProps(store, props) { |
53 | | - const { dispatch } = store; |
| 53 | + const { dispatch } = store |
54 | 54 | const dispatchProps = shouldUpdateDispatchProps ? |
55 | 55 | finalMapDispatchToProps(dispatch, props) : |
56 | | - finalMapDispatchToProps(dispatch); |
| 56 | + finalMapDispatchToProps(dispatch) |
57 | 57 |
|
58 | 58 | invariant( |
59 | 59 | isPlainObject(dispatchProps), |
60 | 60 | '`mapDispatchToProps` must return an object. Instead received %s.', |
61 | 61 | dispatchProps |
62 | | - ); |
63 | | - return dispatchProps; |
| 62 | + ) |
| 63 | + return dispatchProps |
64 | 64 | } |
65 | 65 |
|
66 | 66 | function computeNextState(stateProps, dispatchProps, parentProps) { |
67 | | - const mergedProps = finalMergeProps(stateProps, dispatchProps, parentProps); |
| 67 | + const mergedProps = finalMergeProps(stateProps, dispatchProps, parentProps) |
68 | 68 | invariant( |
69 | 69 | isPlainObject(mergedProps), |
70 | 70 | '`mergeProps` must return an object. Instead received %s.', |
71 | 71 | mergedProps |
72 | | - ); |
73 | | - return mergedProps; |
| 72 | + ) |
| 73 | + return mergedProps |
74 | 74 | } |
75 | 75 |
|
76 | 76 | return function wrapWithConnect(WrappedComponent) { |
77 | 77 | class Connect extends Component { |
78 | 78 | shouldComponentUpdate(nextProps, nextState) { |
79 | 79 | if (!pure) { |
80 | | - this.updateStateProps(nextProps); |
81 | | - this.updateDispatchProps(nextProps); |
82 | | - this.updateState(nextProps); |
83 | | - return true; |
| 80 | + this.updateStateProps(nextProps) |
| 81 | + this.updateDispatchProps(nextProps) |
| 82 | + this.updateState(nextProps) |
| 83 | + return true |
84 | 84 | } |
85 | 85 |
|
86 | | - const storeChanged = nextState.storeState !== this.state.storeState; |
87 | | - const propsChanged = !shallowEqual(nextProps, this.props); |
88 | | - let mapStateProducedChange = false; |
89 | | - let dispatchPropsChanged = false; |
| 86 | + const storeChanged = nextState.storeState !== this.state.storeState |
| 87 | + const propsChanged = !shallowEqual(nextProps, this.props) |
| 88 | + let mapStateProducedChange = false |
| 89 | + let dispatchPropsChanged = false |
90 | 90 |
|
91 | 91 | if (storeChanged || (propsChanged && shouldUpdateStateProps)) { |
92 | | - mapStateProducedChange = this.updateStateProps(nextProps); |
| 92 | + mapStateProducedChange = this.updateStateProps(nextProps) |
93 | 93 | } |
94 | 94 |
|
95 | 95 | if (propsChanged && shouldUpdateDispatchProps) { |
96 | | - dispatchPropsChanged = this.updateDispatchProps(nextProps); |
| 96 | + dispatchPropsChanged = this.updateDispatchProps(nextProps) |
97 | 97 | } |
98 | 98 |
|
99 | 99 | if (propsChanged || mapStateProducedChange || dispatchPropsChanged) { |
100 | | - this.updateState(nextProps); |
101 | | - return true; |
| 100 | + this.updateState(nextProps) |
| 101 | + return true |
102 | 102 | } |
103 | 103 |
|
104 | | - return false; |
| 104 | + return false |
105 | 105 | } |
106 | 106 |
|
107 | 107 | constructor(props, context) { |
108 | | - super(props, context); |
109 | | - this.version = version; |
110 | | - this.store = props.store || context.store; |
| 108 | + super(props, context) |
| 109 | + this.version = version |
| 110 | + this.store = props.store || context.store |
111 | 111 |
|
112 | 112 | invariant(this.store, |
113 | 113 | `Could not find "store" in either the context or ` + |
114 | 114 | `props of "${this.constructor.displayName}". ` + |
115 | 115 | `Either wrap the root component in a <Provider>, ` + |
116 | 116 | `or explicitly pass "store" as a prop to "${this.constructor.displayName}".` |
117 | | - ); |
| 117 | + ) |
118 | 118 |
|
119 | | - this.stateProps = computeStateProps(this.store, props); |
120 | | - this.dispatchProps = computeDispatchProps(this.store, props); |
121 | | - this.state = { storeState: null }; |
122 | | - this.updateState(); |
| 119 | + this.stateProps = computeStateProps(this.store, props) |
| 120 | + this.dispatchProps = computeDispatchProps(this.store, props) |
| 121 | + this.state = { storeState: null } |
| 122 | + this.updateState() |
123 | 123 | } |
124 | 124 |
|
125 | 125 | computeNextState(props = this.props) { |
126 | 126 | return computeNextState( |
127 | 127 | this.stateProps, |
128 | 128 | this.dispatchProps, |
129 | 129 | props |
130 | | - ); |
| 130 | + ) |
131 | 131 | } |
132 | 132 |
|
133 | 133 | updateStateProps(props = this.props) { |
134 | | - const nextStateProps = computeStateProps(this.store, props); |
| 134 | + const nextStateProps = computeStateProps(this.store, props) |
135 | 135 | if (shallowEqual(nextStateProps, this.stateProps)) { |
136 | | - return false; |
| 136 | + return false |
137 | 137 | } |
138 | 138 |
|
139 | | - this.stateProps = nextStateProps; |
140 | | - return true; |
| 139 | + this.stateProps = nextStateProps |
| 140 | + return true |
141 | 141 | } |
142 | 142 |
|
143 | 143 | updateDispatchProps(props = this.props) { |
144 | | - const nextDispatchProps = computeDispatchProps(this.store, props); |
| 144 | + const nextDispatchProps = computeDispatchProps(this.store, props) |
145 | 145 | if (shallowEqual(nextDispatchProps, this.dispatchProps)) { |
146 | | - return false; |
| 146 | + return false |
147 | 147 | } |
148 | 148 |
|
149 | | - this.dispatchProps = nextDispatchProps; |
150 | | - return true; |
| 149 | + this.dispatchProps = nextDispatchProps |
| 150 | + return true |
151 | 151 | } |
152 | 152 |
|
153 | 153 | updateState(props = this.props) { |
154 | | - this.nextState = this.computeNextState(props); |
| 154 | + this.nextState = this.computeNextState(props) |
155 | 155 | } |
156 | 156 |
|
157 | 157 | isSubscribed() { |
158 | | - return typeof this.unsubscribe === 'function'; |
| 158 | + return typeof this.unsubscribe === 'function' |
159 | 159 | } |
160 | 160 |
|
161 | 161 | trySubscribe() { |
162 | 162 | if (shouldSubscribe && !this.unsubscribe) { |
163 | | - this.unsubscribe = this.store.subscribe(::this.handleChange); |
164 | | - this.handleChange(); |
| 163 | + this.unsubscribe = this.store.subscribe(::this.handleChange) |
| 164 | + this.handleChange() |
165 | 165 | } |
166 | 166 | } |
167 | 167 |
|
168 | 168 | tryUnsubscribe() { |
169 | 169 | if (this.unsubscribe) { |
170 | | - this.unsubscribe(); |
171 | | - this.unsubscribe = null; |
| 170 | + this.unsubscribe() |
| 171 | + this.unsubscribe = null |
172 | 172 | } |
173 | 173 | } |
174 | 174 |
|
175 | 175 | componentDidMount() { |
176 | | - this.trySubscribe(); |
| 176 | + this.trySubscribe() |
177 | 177 | } |
178 | 178 |
|
179 | 179 | componentWillUnmount() { |
180 | | - this.tryUnsubscribe(); |
| 180 | + this.tryUnsubscribe() |
181 | 181 | } |
182 | 182 |
|
183 | 183 | handleChange() { |
184 | 184 | if (!this.unsubscribe) { |
185 | | - return; |
| 185 | + return |
186 | 186 | } |
187 | 187 |
|
188 | 188 | this.setState({ |
189 | 189 | storeState: this.store.getState() |
190 | | - }); |
| 190 | + }) |
191 | 191 | } |
192 | 192 |
|
193 | 193 | getWrappedInstance() { |
194 | 194 | invariant(withRef, |
195 | 195 | `To access the wrapped instance, you need to specify ` + |
196 | 196 | `{ withRef: true } as the fourth argument of the connect() call.` |
197 | | - ); |
| 197 | + ) |
198 | 198 |
|
199 | | - return this.refs.wrappedInstance; |
| 199 | + return this.refs.wrappedInstance |
200 | 200 | } |
201 | 201 |
|
202 | 202 | render() { |
203 | | - const ref = withRef ? 'wrappedInstance' : null; |
| 203 | + const ref = withRef ? 'wrappedInstance' : null |
204 | 204 | return ( |
205 | 205 | <WrappedComponent {...this.nextState} ref={ref} /> |
206 | | - ); |
| 206 | + ) |
207 | 207 | } |
208 | 208 | } |
209 | 209 |
|
210 | | - Connect.displayName = `Connect(${getDisplayName(WrappedComponent)})`; |
211 | | - Connect.WrappedComponent = WrappedComponent; |
| 210 | + Connect.displayName = `Connect(${getDisplayName(WrappedComponent)})` |
| 211 | + Connect.WrappedComponent = WrappedComponent |
212 | 212 | Connect.contextTypes = { |
213 | 213 | store: storeShape |
214 | | - }; |
| 214 | + } |
215 | 215 | Connect.propTypes = { |
216 | 216 | store: storeShape |
217 | | - }; |
| 217 | + } |
218 | 218 |
|
219 | 219 | if (process.env.NODE_ENV !== 'production') { |
220 | 220 | Connect.prototype.componentWillUpdate = function componentWillUpdate() { |
221 | 221 | if (this.version === version) { |
222 | | - return; |
| 222 | + return |
223 | 223 | } |
224 | 224 |
|
225 | 225 | // We are hot reloading! |
226 | | - this.version = version; |
| 226 | + this.version = version |
227 | 227 |
|
228 | 228 | // Update the state and bindings. |
229 | | - this.trySubscribe(); |
230 | | - this.updateStateProps(); |
231 | | - this.updateDispatchProps(); |
232 | | - this.updateState(); |
233 | | - }; |
| 229 | + this.trySubscribe() |
| 230 | + this.updateStateProps() |
| 231 | + this.updateDispatchProps() |
| 232 | + this.updateState() |
| 233 | + } |
234 | 234 | } |
235 | 235 |
|
236 | | - return hoistStatics(Connect, WrappedComponent); |
237 | | - }; |
| 236 | + return hoistStatics(Connect, WrappedComponent) |
| 237 | + } |
238 | 238 | } |
0 commit comments