Skip to content

Commit

Permalink
Revert connect and provider to v5.0.7's versions
Browse files Browse the repository at this point in the history
  • Loading branch information
MiyamotoSatoshi committed Aug 13, 2018
1 parent 6aec213 commit ad66028
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 53 deletions.
4 changes: 2 additions & 2 deletions src/components/Provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ export function createProvider(storeKey = 'store') {
}

if (process.env.NODE_ENV !== 'production') {
Provider.prototype.componentDidUpdate = function () {
if (this[storeKey] !== this.props.store) {
Provider.prototype.componentWillReceiveProps = function (nextProps) {
if (this[storeKey] !== nextProps.store) {
warnAboutReceivingStore()
}
}
Expand Down
108 changes: 57 additions & 51 deletions src/components/connectAdvanced.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,32 @@
import hoistStatics from 'hoist-non-react-statics'
import invariant from 'invariant'
import { Component, createElement } from 'react'
import { polyfill } from 'react-lifecycles-compat'

import Subscription from '../utils/Subscription'
import { storeShape, subscriptionShape } from '../utils/PropTypes'

let hotReloadingVersion = 0
const dummyState = {}
function noop() {}
function makeUpdater(sourceSelector, store) {
return function updater(props, prevState) {
try {
const nextProps = sourceSelector(store.getState(), props)
if (nextProps !== prevState.props || prevState.error) {
return {
shouldComponentUpdate: true,
props: nextProps,
error: null,
function makeSelectorStateful(sourceSelector, store) {
// wrap the selector in an object that tracks its results between runs.
const selector = {
run: function runComponentSelector(props) {
try {
const nextProps = sourceSelector(store.getState(), props)
if (nextProps !== selector.props || selector.error) {
selector.shouldComponentUpdate = true
selector.props = nextProps
selector.error = null
}
}
return {
shouldComponentUpdate: false,
}
} catch (error) {
return {
shouldComponentUpdate: true,
error,
} catch (error) {
selector.shouldComponentUpdate = true
selector.error = error
}
}
}

return selector
}

export default function connectAdvanced(
Expand Down Expand Up @@ -88,10 +86,6 @@ export default function connectAdvanced(
[subscriptionKey]: subscriptionShape,
}

function getDerivedStateFromProps(nextProps, prevState) {
return prevState.updater(nextProps, prevState)
}

return function wrapWithConnect(WrappedComponent) {
invariant(
typeof WrappedComponent == 'function',
Expand Down Expand Up @@ -123,6 +117,7 @@ export default function connectAdvanced(
super(props, context)

this.version = version
this.state = {}
this.renderCount = 0
this.store = props[storeKey] || context[storeKey]
this.propsMode = Boolean(props[storeKey])
Expand All @@ -134,9 +129,7 @@ export default function connectAdvanced(
`or explicitly pass "${storeKey}" as a prop to "${displayName}".`
)

this.state = {
updater: this.createUpdater()
}
this.initSelector()
this.initSubscription()
}

Expand All @@ -159,19 +152,25 @@ export default function connectAdvanced(
// dispatching an action in its componentWillMount, we have to re-run the select and maybe
// re-render.
this.subscription.trySubscribe()
this.runUpdater()
this.selector.run(this.props)
if (this.selector.shouldComponentUpdate) this.forceUpdate()
}

componentWillReceiveProps(nextProps) {
this.selector.run(nextProps)
}

shouldComponentUpdate(_, nextState) {
return nextState.shouldComponentUpdate
shouldComponentUpdate() {
return this.selector.shouldComponentUpdate
}

componentWillUnmount() {
if (this.subscription) this.subscription.tryUnsubscribe()
this.subscription = null
this.notifyNestedSubs = noop
this.store = null
this.isUnmounted = true
this.selector.run = noop
this.selector.shouldComponentUpdate = false
}

getWrappedInstance() {
Expand All @@ -186,17 +185,10 @@ export default function connectAdvanced(
this.wrappedInstance = ref
}

createUpdater() {
initSelector() {
const sourceSelector = selectorFactory(this.store.dispatch, selectorFactoryOptions)
return makeUpdater(sourceSelector, this.store)
}

runUpdater(callback = noop) {
if (this.isUnmounted) {
return
}

this.setState(prevState => prevState.updater(this.props, prevState), callback)
this.selector = makeSelectorStateful(sourceSelector, this.store)
this.selector.run(this.props)
}

initSubscription() {
Expand All @@ -217,7 +209,24 @@ export default function connectAdvanced(
}

onStateChange() {
this.runUpdater(this.notifyNestedSubs)
this.selector.run(this.props)

if (!this.selector.shouldComponentUpdate) {
this.notifyNestedSubs()
} else {
this.componentDidUpdate = this.notifyNestedSubsOnComponentDidUpdate
this.setState(dummyState)
}
}

notifyNestedSubsOnComponentDidUpdate() {
// `componentDidUpdate` is conditionally implemented when `onStateChange` determines it
// needs to notify nested subs. Once called, it unimplements itself until further state
// changes occur. Doing it this way vs having a permanent `componentDidUpdate` that does
// a boolean check every time avoids an extra method call most of the time, resulting
// in some perf boost.
this.componentDidUpdate = undefined
this.notifyNestedSubs()
}

isSubscribed() {
Expand All @@ -238,10 +247,13 @@ export default function connectAdvanced(
}

render() {
if (this.state.error) {
throw this.state.error
const selector = this.selector
selector.shouldComponentUpdate = false

if (selector.error) {
throw selector.error
} else {
return createElement(WrappedComponent, this.addExtraProps(this.state.props))
return createElement(WrappedComponent, this.addExtraProps(selector.props))
}
}
}
Expand All @@ -251,13 +263,13 @@ export default function connectAdvanced(
Connect.childContextTypes = childContextTypes
Connect.contextTypes = contextTypes
Connect.propTypes = contextTypes
Connect.getDerivedStateFromProps = getDerivedStateFromProps

if (process.env.NODE_ENV !== 'production') {
Connect.prototype.componentDidUpdate = function componentDidUpdate() {
Connect.prototype.componentWillUpdate = function componentWillUpdate() {
// We are hot reloading!
if (this.version !== version) {
this.version = version
this.initSelector()

// If any connected descendants don't hot reload (and resubscribe in the process), their
// listeners will be lost when we unsubscribe. Unfortunately, by copying over all
Expand All @@ -275,16 +287,10 @@ export default function connectAdvanced(
this.subscription.trySubscribe()
oldListeners.forEach(listener => this.subscription.listeners.subscribe(listener))
}

const updater = this.createUpdater()
this.setState({updater})
this.runUpdater()
}
}
}

polyfill(Connect)

return hoistStatics(Connect, WrappedComponent)
}
}

0 comments on commit ad66028

Please sign in to comment.