Skip to content

Commit 9ee1a36

Browse files
committed
Move selector to state in order to be able to use gDSFP
1 parent 94f0b8a commit 9ee1a36

File tree

3 files changed

+36
-23
lines changed

3 files changed

+36
-23
lines changed

package-lock.json

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@
5353
"lodash": "^4.17.5",
5454
"lodash-es": "^4.17.5",
5555
"loose-envify": "^1.1.0",
56-
"prop-types": "^15.6.1"
56+
"prop-types": "^15.6.1",
57+
"react-lifecycles-compat": "^1.1.4"
5758
},
5859
"devDependencies": {
5960
"babel-cli": "^6.26.0",

src/components/connectAdvanced.js

+29-22
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import hoistStatics from 'hoist-non-react-statics'
22
import invariant from 'invariant'
33
import { Component, createElement } from 'react'
4+
import polyfill from 'react-lifecycles-compat'
45

56
import Subscription from '../utils/Subscription'
67
import { storeShape, subscriptionShape } from '../utils/PropTypes'
@@ -23,6 +24,10 @@ function makeSelectorStateful(sourceSelector, store) {
2324
selector.shouldComponentUpdate = true
2425
selector.error = error
2526
}
27+
},
28+
clean: function cleanComponentSelector() {
29+
selector.run = noop
30+
selector.shouldComponentUpdate = false
2631
}
2732
}
2833

@@ -86,6 +91,11 @@ export default function connectAdvanced(
8691
[subscriptionKey]: subscriptionShape,
8792
}
8893

94+
function getDerivedStateFromProps(nextProps, prevState) {
95+
prevState.selector.run(nextProps)
96+
return null
97+
}
98+
8999
return function wrapWithConnect(WrappedComponent) {
90100
invariant(
91101
typeof WrappedComponent == 'function',
@@ -117,7 +127,6 @@ export default function connectAdvanced(
117127
super(props, context)
118128

119129
this.version = version
120-
this.state = {}
121130
this.renderCount = 0
122131
this.store = props[storeKey] || context[storeKey]
123132
this.propsMode = Boolean(props[storeKey])
@@ -129,7 +138,9 @@ export default function connectAdvanced(
129138
`or explicitly pass "${storeKey}" as a prop to "${displayName}".`
130139
)
131140

132-
this.initSelector()
141+
this.state = {
142+
selector: this.createSelector()
143+
}
133144
this.initSubscription()
134145
}
135146

@@ -152,24 +163,20 @@ export default function connectAdvanced(
152163
// dispatching an action in its componentWillMount, we have to re-run the select and maybe
153164
// re-render.
154165
this.subscription.trySubscribe()
155-
this.selector.run(this.props)
156-
if (this.selector.shouldComponentUpdate) this.forceUpdate()
166+
this.state.selector.run(this.props)
167+
if (this.state.selector.shouldComponentUpdate) this.forceUpdate()
157168
}
158169

159-
shouldComponentUpdate(nextProps) {
160-
if (nextProps !== this.props) {
161-
this.selector.run(nextProps)
162-
}
163-
return this.selector.shouldComponentUpdate
170+
shouldComponentUpdate(nextProps, nextState) {
171+
return nextState.selector.shouldComponentUpdate
164172
}
165173

166174
componentWillUnmount() {
167175
if (this.subscription) this.subscription.tryUnsubscribe()
168176
this.subscription = null
169177
this.notifyNestedSubs = noop
170178
this.store = null
171-
this.selector.run = noop
172-
this.selector.shouldComponentUpdate = false
179+
this.state.selector.clean()
173180
}
174181

175182
getWrappedInstance() {
@@ -184,10 +191,9 @@ export default function connectAdvanced(
184191
this.wrappedInstance = ref
185192
}
186193

187-
initSelector() {
194+
createSelector() {
188195
const sourceSelector = selectorFactory(this.store.dispatch, selectorFactoryOptions)
189-
this.selector = makeSelectorStateful(sourceSelector, this.store)
190-
this.selector.run(this.props)
196+
return makeSelectorStateful(sourceSelector, this.store)
191197
}
192198

193199
initSubscription() {
@@ -208,9 +214,9 @@ export default function connectAdvanced(
208214
}
209215

210216
onStateChange() {
211-
this.selector.run(this.props)
217+
this.state.selector.run(this.props)
212218

213-
if (!this.selector.shouldComponentUpdate) {
219+
if (!this.state.selector.shouldComponentUpdate) {
214220
this.notifyNestedSubs()
215221
} else {
216222
this.componentDidUpdate = this.notifyNestedSubsOnComponentDidUpdate
@@ -246,10 +252,7 @@ export default function connectAdvanced(
246252
}
247253

248254
render() {
249-
const selector = this.selector
250-
251-
// Handle forceUpdate
252-
if (!selector.shouldComponentUpdate) selector.run(this.props)
255+
const selector = this.state.selector
253256

254257
selector.shouldComponentUpdate = false
255258

@@ -266,13 +269,13 @@ export default function connectAdvanced(
266269
Connect.childContextTypes = childContextTypes
267270
Connect.contextTypes = contextTypes
268271
Connect.propTypes = contextTypes
272+
Connect.getDerivedStateFromProps = getDerivedStateFromProps
269273

270274
if (process.env.NODE_ENV !== 'production') {
271275
Connect.prototype.componentDidUpdate = function componentDidUpdate() {
272276
// We are hot reloading!
273277
if (this.version !== version) {
274278
this.version = version
275-
this.initSelector()
276279

277280
// If any connected descendants don't hot reload (and resubscribe in the process), their
278281
// listeners will be lost when we unsubscribe. Unfortunately, by copying over all
@@ -291,11 +294,15 @@ export default function connectAdvanced(
291294
oldListeners.forEach(listener => this.subscription.listeners.subscribe(listener))
292295
}
293296

294-
if (this.selector.shouldComponentUpdate) this.setState(dummyState)
297+
const selector = this.createSelector()
298+
selector.run(this.props)
299+
this.setState({selector})
295300
}
296301
}
297302
}
298303

304+
polyfill(Connect)
305+
299306
return hoistStatics(Connect, WrappedComponent)
300307
}
301308
}

0 commit comments

Comments
 (0)