diff --git a/modules/ContextUtils.js b/modules/ContextUtils.js
index 03edb36e4e..ab8e7fc85a 100644
--- a/modules/ContextUtils.js
+++ b/modules/ContextUtils.js
@@ -1,4 +1,4 @@
-import React, { PropTypes } from 'react'
+import { PropTypes } from 'react'
// Works around issues with context updates failing to propagate.
// https://github.com/facebook/react/issues/2517
@@ -13,14 +13,13 @@ function makeContextName(name) {
return `@@contextSubscriber/${name}`
}
-export function createContextProvider(name) {
+export function ContextProvider(name) {
const contextName = makeContextName(name)
+ const listenersKey = `${contextName}/listeners`
+ const eventIndexKey = `${contextName}/eventIndex`
+ const subscribeKey = `${contextName}/subscribe`
- const ContextProvider = React.createClass({
- propTypes: {
- children: PropTypes.node.isRequired
- },
-
+ return {
childContextTypes: {
[contextName]: contextProviderShape.isRequired
},
@@ -28,46 +27,47 @@ export function createContextProvider(name) {
getChildContext() {
return {
[contextName]: {
- subscribe: this.subscribe,
- eventIndex: this.eventIndex
+ eventIndex: this[eventIndexKey],
+ subscribe: this[subscribeKey]
}
}
},
componentWillMount() {
- this.eventIndex = 0
- this.listeners = []
+ this[listenersKey] = []
+ this[eventIndexKey] = 0
},
componentWillReceiveProps() {
- this.eventIndex++
+ this[eventIndexKey]++
},
componentDidUpdate() {
- this.listeners.forEach(listener => listener(this.eventIndex))
+ this[listenersKey].forEach(listener =>
+ listener(this[eventIndexKey])
+ )
},
- subscribe(listener) {
+ [subscribeKey](listener) {
// No need to immediately call listener here.
- this.listeners.push(listener)
+ this[listenersKey].push(listener)
return () => {
- this.listeners = this.listeners.filter(item => item !== listener)
+ this[listenersKey] = this[listenersKey].filter(item =>
+ item !== listener
+ )
}
- },
-
- render() {
- return this.props.children
}
- })
-
- return ContextProvider
+ }
}
-export function connectToContext(WrappedComponent, name) {
+export function ContextSubscriber(name) {
const contextName = makeContextName(name)
+ const lastRenderedEventIndexKey = `${contextName}/lastRenderedEventIndex`
+ const handleContextUpdateKey = `${contextName}/handleContextUpdate`
+ const unsubscribeKey = `${contextName}/unsubscribe`
- const ContextSubscriber = React.createClass({
+ return {
contextTypes: {
[contextName]: contextProviderShape
},
@@ -78,7 +78,7 @@ export function connectToContext(WrappedComponent, name) {
}
return {
- lastRenderedEventIndex: this.context[contextName].eventIndex
+ [lastRenderedEventIndexKey]: this.context[contextName].eventIndex
}
},
@@ -87,8 +87,8 @@ export function connectToContext(WrappedComponent, name) {
return
}
- this.unsubscribe = this.context[contextName].subscribe(
- this.handleContextUpdate
+ this[unsubscribeKey] = this.context[contextName].subscribe(
+ this[handleContextUpdateKey]
)
},
@@ -98,29 +98,23 @@ export function connectToContext(WrappedComponent, name) {
}
this.setState({
- lastRenderedEventIndex: this.context[contextName].eventIndex
+ [lastRenderedEventIndexKey]: this.context[contextName].eventIndex
})
},
componentWillUnmount() {
- if (!this.unsubscribe) {
+ if (!this[unsubscribeKey]) {
return
}
- this.unsubscribe()
- this.unsubscribe = null
+ this[unsubscribeKey]()
+ this[unsubscribeKey] = null
},
- handleContextUpdate(eventIndex) {
- if (eventIndex !== this.state.lastRenderedEventIndex) {
- this.setState({ lastRenderedEventIndex: eventIndex })
+ [handleContextUpdateKey](eventIndex) {
+ if (eventIndex !== this.state[lastRenderedEventIndexKey]) {
+ this.setState({ [lastRenderedEventIndexKey]: eventIndex })
}
- },
-
- render() {
- return
}
- })
-
- return ContextSubscriber
+ }
}
diff --git a/modules/Link.js b/modules/Link.js
index ee23fd5bad..c658187c7a 100644
--- a/modules/Link.js
+++ b/modules/Link.js
@@ -1,6 +1,6 @@
import React from 'react'
import { routerShape } from './PropTypes'
-import { connectToContext } from './ContextUtils'
+import { ContextSubscriber } from './ContextUtils'
const { bool, object, string, func, oneOfType } = React.PropTypes
@@ -41,6 +41,8 @@ function isEmptyObject(object) {
*/
const Link = React.createClass({
+ mixins: [ ContextSubscriber('router') ],
+
contextTypes: {
router: routerShape
},
@@ -122,4 +124,4 @@ const Link = React.createClass({
})
-export default connectToContext(Link, 'router', object)
+export default Link
diff --git a/modules/RouterContext.js b/modules/RouterContext.js
index 3199cb6e56..271d813308 100644
--- a/modules/RouterContext.js
+++ b/modules/RouterContext.js
@@ -2,11 +2,10 @@ import invariant from 'invariant'
import React from 'react'
import getRouteParams from './getRouteParams'
-import { createContextProvider } from './ContextUtils'
+import { ContextProvider } from './ContextUtils'
import { isReactChildren } from './RouteUtils'
const { array, func, object } = React.PropTypes
-const RouterContextProvider = createContextProvider('router', object.isRequired)
/**
* A renders the component tree for a given router state
@@ -14,6 +13,8 @@ const RouterContextProvider = createContextProvider('router', object.isRequired)
*/
const RouterContext = React.createClass({
+ mixins: [ ContextProvider('router') ],
+
propTypes: {
router: object.isRequired,
routes: array.isRequired,
@@ -90,21 +91,12 @@ const RouterContext = React.createClass({
}, element)
}
- const isEmpty = element === null || element === false
invariant(
- isEmpty || React.isValidElement(element),
+ element === null || element === false || React.isValidElement(element),
'The root route must render a single element'
)
- if (isEmpty) {
- return element
- }
-
- return (
-
- {element}
-
- )
+ return element
}
})