diff --git a/src/components/Provider.js b/src/components/Provider.js
index ac77a003e..c30bc3b55 100644
--- a/src/components/Provider.js
+++ b/src/components/Provider.js
@@ -1,8 +1,10 @@
-import { Component, Children } from 'react'
+import React, { Component, Children } from 'react'
import PropTypes from 'prop-types'
import { storeShape, subscriptionShape } from '../utils/PropTypes'
import warning from '../utils/warning'
+import {ReactReduxContext} from "./context";
+
let didWarnAboutReceivingStore = false
function warnAboutReceivingStore() {
if (didWarnAboutReceivingStore) {
@@ -20,20 +22,48 @@ function warnAboutReceivingStore() {
}
export function createProvider(storeKey = 'store', subKey) {
- const subscriptionKey = subKey || `${storeKey}Subscription`
+ //const subscriptionKey = subKey || `${storeKey}Subscription`
class Provider extends Component {
+ /*
getChildContext() {
return { [storeKey]: this[storeKey], [subscriptionKey]: null }
}
+ */
constructor(props, context) {
super(props, context)
- this[storeKey] = props.store;
+ //this[storeKey] = props.store;
+
+ const {store} = props;
+
+ if(!store || !store.getState || !store.dispatch) {
+ throw new Error("Must pass a valid Redux store as a prop to Provider");
+ }
+
+ this.state = {
+ storeState : store.getState(),
+ dispatch : store.dispatch,
+ };
+ }
+
+ componentDidMount() {
+ const {store} = this.props;
+
+ this.unsubscribe = store.subscribe( () => {
+ console.log("Provider subscription running");
+ this.setState({storeState : store.getState()});
+ });
}
render() {
- return Children.only(this.props.children)
+ console.log("Provider re-rendering");
+
+ return (
+
+ {Children.only(this.props.children)}
+
+ );
}
}
@@ -45,14 +75,17 @@ export function createProvider(storeKey = 'store', subKey) {
}
}
+
Provider.propTypes = {
store: storeShape.isRequired,
children: PropTypes.element.isRequired,
}
+ /*
Provider.childContextTypes = {
[storeKey]: storeShape.isRequired,
[subscriptionKey]: subscriptionShape,
}
+ */
return Provider
}
diff --git a/src/components/connectAdvanced.js b/src/components/connectAdvanced.js
index 3fff8ee26..ededb86b3 100644
--- a/src/components/connectAdvanced.js
+++ b/src/components/connectAdvanced.js
@@ -1,19 +1,20 @@
import hoistStatics from 'hoist-non-react-statics'
import invariant from 'invariant'
-import { Component, createElement } from 'react'
+import React, { Component, createElement } from 'react'
import Subscription from '../utils/Subscription'
+import {ReactReduxContext} from "./context";
import { storeShape, subscriptionShape } from '../utils/PropTypes'
let hotReloadingVersion = 0
const dummyState = {}
function noop() {}
-function makeSelectorStateful(sourceSelector, store) {
+function makeSelectorStateful(sourceSelector) {
// wrap the selector in an object that tracks its results between runs.
const selector = {
- run: function runComponentSelector(props) {
+ run: function runComponentSelector(props, storeState) {
try {
- const nextProps = sourceSelector(store.getState(), props)
+ const nextProps = sourceSelector(storeState, props)
if (nextProps !== selector.props || selector.error) {
selector.shouldComponentUpdate = true
selector.props = nextProps
@@ -78,6 +79,7 @@ export default function connectAdvanced(
const subscriptionKey = storeKey + 'Subscription'
const version = hotReloadingVersion++
+ /*
const contextTypes = {
[storeKey]: storeShape,
[subscriptionKey]: subscriptionShape,
@@ -85,10 +87,11 @@ export default function connectAdvanced(
const childContextTypes = {
[subscriptionKey]: subscriptionShape,
}
+ */
return function wrapWithConnect(WrappedComponent) {
invariant(
- typeof WrappedComponent == 'function',
+ typeof WrappedComponent === 'function',
`You must pass a component to the function returned by ` +
`${methodName}. Instead received ${JSON.stringify(WrappedComponent)}`
)
@@ -117,22 +120,30 @@ export default function connectAdvanced(
super(props, context)
this.version = version
- this.state = {}
+ //this.state = {}
this.renderCount = 0
- this.store = props[storeKey] || context[storeKey]
- this.propsMode = Boolean(props[storeKey])
+ //this.store = props[storeKey] || context[storeKey]
+ //this.propsMode = Boolean(props[storeKey])
+
+ this.storeState = null;
+
+
this.setWrappedInstance = this.setWrappedInstance.bind(this)
+ this.renderChild = this.renderChild.bind(this);
+ /*
invariant(this.store,
`Could not find "${storeKey}" in either the context or props of ` +
`"${displayName}". Either wrap the root component in a , ` +
`or explicitly pass "${storeKey}" as a prop to "${displayName}".`
)
+ */
- this.initSelector()
- this.initSubscription()
+ //this.initSelector()
+ //this.initSubscription()
}
+ /*
getChildContext() {
// If this component received store from props, its subscription should be transparent
// to any descendants receiving store+subscription from context; it passes along
@@ -141,6 +152,7 @@ export default function connectAdvanced(
const subscription = this.propsMode ? null : this.subscription
return { [subscriptionKey]: subscription || this.context[subscriptionKey] }
}
+ */
componentDidMount() {
if (!shouldHandleStateChanges) return
@@ -151,24 +163,28 @@ export default function connectAdvanced(
// To handle the case where a child component may have triggered a state change by
// dispatching an action in its componentWillMount, we have to re-run the select and maybe
// re-render.
- this.subscription.trySubscribe()
- this.selector.run(this.props)
+ //this.subscription.trySubscribe()
+ this.selector.run(this.props, this.storeState);
if (this.selector.shouldComponentUpdate) this.forceUpdate()
}
- componentWillReceiveProps(nextProps) {
- this.selector.run(nextProps)
+
+ UNSAFE_componentWillReceiveProps(nextProps) {
+ this.selector.run(nextProps, this.storeState);
}
+
+
shouldComponentUpdate() {
return this.selector.shouldComponentUpdate
}
+
componentWillUnmount() {
- if (this.subscription) this.subscription.tryUnsubscribe()
- this.subscription = null
+ //if (this.subscription) this.subscription.tryUnsubscribe()
+ //this.subscription = null
this.notifyNestedSubs = noop
- this.store = null
+ //this.store = null
this.selector.run = noop
this.selector.shouldComponentUpdate = false
}
@@ -185,13 +201,22 @@ export default function connectAdvanced(
this.wrappedInstance = ref
}
+ /*
initSelector() {
const sourceSelector = selectorFactory(this.store.dispatch, selectorFactoryOptions)
this.selector = makeSelectorStateful(sourceSelector, this.store)
this.selector.run(this.props)
}
+ */
+
+ initSelector(dispatch, storeState) {
+ const sourceSelector = selectorFactory(dispatch, selectorFactoryOptions)
+ this.selector = makeSelectorStateful(sourceSelector)
+ this.selector.run(this.props, storeState);
+ }
initSubscription() {
+ /*
if (!shouldHandleStateChanges) return
// parentSub's source should match where store came from: props vs. context. A component
@@ -206,6 +231,7 @@ export default function connectAdvanced(
// listeners logic is changed to not call listeners that have been unsubscribed in the
// middle of the notification loop.
this.notifyNestedSubs = this.subscription.notifyNestedSubs.bind(this.subscription)
+ */
}
onStateChange() {
@@ -229,12 +255,17 @@ export default function connectAdvanced(
this.notifyNestedSubs()
}
+ /*
isSubscribed() {
return Boolean(this.subscription) && this.subscription.isSubscribed()
}
+ */
addExtraProps(props) {
- if (!withRef && !renderCountProp && !(this.propsMode && this.subscription)) return props
+ //if (!withRef && !renderCountProp && !(this.propsMode && this.subscription)) return props
+ if (!withRef && !renderCountProp) return props;
+
+
// make a shallow copy so that fields added don't leak to the original selector.
// this is especially important for 'ref' since that's a reference back to the component
// instance. a singleton memoized selector would then be holding a reference to the
@@ -242,10 +273,51 @@ export default function connectAdvanced(
const withExtras = { ...props }
if (withRef) withExtras.ref = this.setWrappedInstance
if (renderCountProp) withExtras[renderCountProp] = this.renderCount++
- if (this.propsMode && this.subscription) withExtras[subscriptionKey] = this.subscription
+ //if (this.propsMode && this.subscription) withExtras[subscriptionKey] = this.subscription
return withExtras
}
+ renderChild(providerValue) {
+ const {storeState, dispatch} = providerValue;
+
+ this.storeState = storeState;
+
+ //console.log(`Running renderChild (${displayName})`, storeState, this.props);
+
+ if(this.selector) {
+ this.selector.run(this.props, storeState);
+ }
+ else {
+ this.initSelector(dispatch, storeState);
+ }
+
+
+
+ if (this.selector.error) {
+ throw this.selector.error
+ }
+ else if(this.selector.shouldComponentUpdate) {
+ console.log(`Re-rendering component (${displayName})`, this.selector.props);
+ this.selector.shouldComponentUpdate = false;
+ this.renderedElement = createElement(WrappedComponent, this.addExtraProps(this.selector.props));
+ }
+ else {
+ //console.log(`Returning existing render result (${displayName})`, this.props)
+ }
+
+ return this.renderedElement;
+ }
+
+ render() {
+ return (
+
+ {this.renderChild}
+
+ )
+ }
+
+ /*
+
render() {
const selector = this.selector
selector.shouldComponentUpdate = false
@@ -256,14 +328,16 @@ export default function connectAdvanced(
return createElement(WrappedComponent, this.addExtraProps(selector.props))
}
}
+ */
}
Connect.WrappedComponent = WrappedComponent
Connect.displayName = displayName
- Connect.childContextTypes = childContextTypes
- Connect.contextTypes = contextTypes
- Connect.propTypes = contextTypes
+ //Connect.childContextTypes = childContextTypes
+ //Connect.contextTypes = contextTypes
+ //Connect.propTypes = contextTypes
+ /*
if (process.env.NODE_ENV !== 'production') {
Connect.prototype.componentWillUpdate = function componentWillUpdate() {
// We are hot reloading!
@@ -290,6 +364,7 @@ export default function connectAdvanced(
}
}
}
+ */
return hoistStatics(Connect, WrappedComponent)
}
diff --git a/src/components/context.js b/src/components/context.js
new file mode 100644
index 000000000..ba029da20
--- /dev/null
+++ b/src/components/context.js
@@ -0,0 +1,3 @@
+import React from "react";
+
+export const ReactReduxContext = React.createContext(null);
\ No newline at end of file