react-router
Version:
A complete routing library for React
115 lines (93 loc) • 3.54 kB
JavaScript
import { PropTypes } from 'react';
// Works around issues with context updates failing to propagate.
// Caveat: the context value is expected to never change its identity.
// https://github.com/facebook/react/issues/2517
// https://github.com/reactjs/react-router/issues/470
var contextProviderShape = PropTypes.shape({
subscribe: PropTypes.func.isRequired,
eventIndex: PropTypes.number.isRequired
});
function makeContextName(name) {
return '@@contextSubscriber/' + name;
}
export function ContextProvider(name) {
var _childContextTypes, _ref2;
var contextName = makeContextName(name);
var listenersKey = contextName + '/listeners';
var eventIndexKey = contextName + '/eventIndex';
var subscribeKey = contextName + '/subscribe';
return _ref2 = {
childContextTypes: (_childContextTypes = {}, _childContextTypes[contextName] = contextProviderShape.isRequired, _childContextTypes),
getChildContext: function getChildContext() {
var _ref;
return _ref = {}, _ref[contextName] = {
eventIndex: this[eventIndexKey],
subscribe: this[subscribeKey]
}, _ref;
},
componentWillMount: function componentWillMount() {
this[listenersKey] = [];
this[eventIndexKey] = 0;
},
componentWillReceiveProps: function componentWillReceiveProps() {
this[eventIndexKey]++;
},
componentDidUpdate: function componentDidUpdate() {
var _this = this;
this[listenersKey].forEach(function (listener) {
return listener(_this[eventIndexKey]);
});
}
}, _ref2[subscribeKey] = function (listener) {
var _this2 = this;
// No need to immediately call listener here.
this[listenersKey].push(listener);
return function () {
_this2[listenersKey] = _this2[listenersKey].filter(function (item) {
return item !== listener;
});
};
}, _ref2;
}
export function ContextSubscriber(name) {
var _contextTypes, _ref4;
var contextName = makeContextName(name);
var lastRenderedEventIndexKey = contextName + '/lastRenderedEventIndex';
var handleContextUpdateKey = contextName + '/handleContextUpdate';
var unsubscribeKey = contextName + '/unsubscribe';
return _ref4 = {
contextTypes: (_contextTypes = {}, _contextTypes[contextName] = contextProviderShape, _contextTypes),
getInitialState: function getInitialState() {
var _ref3;
if (!this.context[contextName]) {
return {};
}
return _ref3 = {}, _ref3[lastRenderedEventIndexKey] = this.context[contextName].eventIndex, _ref3;
},
componentDidMount: function componentDidMount() {
if (!this.context[contextName]) {
return;
}
this[unsubscribeKey] = this.context[contextName].subscribe(this[handleContextUpdateKey]);
},
componentWillReceiveProps: function componentWillReceiveProps() {
var _setState;
if (!this.context[contextName]) {
return;
}
this.setState((_setState = {}, _setState[lastRenderedEventIndexKey] = this.context[contextName].eventIndex, _setState));
},
componentWillUnmount: function componentWillUnmount() {
if (!this[unsubscribeKey]) {
return;
}
this[unsubscribeKey]();
this[unsubscribeKey] = null;
}
}, _ref4[handleContextUpdateKey] = function (eventIndex) {
if (eventIndex !== this.state[lastRenderedEventIndexKey]) {
var _setState2;
this.setState((_setState2 = {}, _setState2[lastRenderedEventIndexKey] = eventIndex, _setState2));
}
}, _ref4;
}