diff --git a/src/components/connectAdvanced.js b/src/components/connectAdvanced.js index 7ad013f23..ff19d87f3 100644 --- a/src/components/connectAdvanced.js +++ b/src/components/connectAdvanced.js @@ -5,6 +5,8 @@ import { Component, PropTypes, createElement } from 'react' import Subscription from '../utils/Subscription' import storeShape from '../utils/storeShape' + +let defaultReact15CompatibilityMode = true let hotReloadingVersion = 0 export default function connectAdvanced( /* @@ -18,7 +20,7 @@ export default function connectAdvanced( Access to dispatch is provided to the factory so selectorFactories can bind actionCreators outside of their selector as an optimization. Options passed to connectAdvanced are passed to - the selectorFactory, along with displayName and WrappedComponent, as the second argument. + the selectorFactory, along with displayName and WrappedComponent, as the second argument. Note that selectorFactory is responsible for all caching/memoization of inbound and outbound props. Do not use connectAdvanced directly without memoizing results between calls to your @@ -35,6 +37,9 @@ export default function connectAdvanced( // probably overridden by wrapper functions such as connect() methodName = 'connectAdvanced', + // temporary compatibility setting for React 15. See Connect constructor for details + react15CompatibilityMode = undefined, + // if defined, the name of the property passed to the wrapped element indicating the number of // calls to render. useful for watching in react devtools for unnecessary re-renders. renderCountProp = undefined, @@ -57,11 +62,12 @@ export default function connectAdvanced( const contextTypes = { [storeKey]: storeShape, - [subscriptionKey]: PropTypes.instanceOf(Subscription) + [subscriptionKey]: PropTypes.instanceOf(Subscription), + react15CompatibilityMode: PropTypes.bool, } const childContextTypes = { [subscriptionKey]: PropTypes.instanceOf(Subscription) - } + } return function wrapWithConnect(WrappedComponent) { invariant( @@ -96,7 +102,19 @@ export default function connectAdvanced( this.state = {} this.renderCount = 0 this.store = this.props[storeKey] || this.context[storeKey] - this.parentSub = this.props[subscriptionKey] || this.context[subscriptionKey] + + // react15CompatibilityMode controls whether the subscription system is used. This is for + // https://github.com/reactjs/react-redux/issues/525 and should be removed completely when + // react-redux's dependency on react is bumped to mimimum v16, which is expected to include + // PR https://github.com/facebook/react/pull/8204 which fixes the issue. + const compatMode = [ + react15CompatibilityMode, + props.react15CompatibilityMode, + context.react15CompatibilityMode, + defaultReact15CompatibilityMode + ].find(cm => cm !== undefined && cm !== null) + this.parentSub = compatMode ? null : props[subscriptionKey] || context[subscriptionKey] + this.setWrappedInstance = this.setWrappedInstance.bind(this) invariant(this.store, @@ -256,3 +274,9 @@ export default function connectAdvanced( return hoistStatics(Connect, WrappedComponent) } } + +connectAdvanced.setDefaultReact15CompatibilityMode = + function setDefaultReact15CompatibilityMode(compat) { + defaultReact15CompatibilityMode = compat + } + diff --git a/src/connect/connect.js b/src/connect/connect.js index cb82945a6..f8254995e 100644 --- a/src/connect/connect.js +++ b/src/connect/connect.js @@ -84,4 +84,6 @@ export function createConnect({ } } -export default createConnect() +const connect = createConnect() +connect.setDefaultReact15CompatibilityMode = connectAdvanced.setDefaultReact15CompatibilityMode +export default connect diff --git a/test/components/Provider.spec.js b/test/components/Provider.spec.js index 66a88cc0d..59ca81b89 100644 --- a/test/components/Provider.spec.js +++ b/test/components/Provider.spec.js @@ -144,7 +144,7 @@ describe('React', () => { // The state from parent props should always be consistent with the current state expect(state).toEqual(parentProps.parentState) return {} - }) + }, null, null, { react15CompatibilityMode: false }) class ChildContainer extends Component { render() { return
diff --git a/test/components/connect.spec.js b/test/components/connect.spec.js index 17a9e5782..d04a80b6e 100644 --- a/test/components/connect.spec.js +++ b/test/components/connect.spec.js @@ -1698,7 +1698,7 @@ describe('React', () => { // The state from parent props should always be consistent with the current state expect(state).toEqual(parentProps.parentState) return {} - }) + }, null, null, { react15CompatibilityMode: false }) class ChildContainer extends Component { render() { return