Skip to content

Commit

Permalink
Switch to parent-based context. Fixes #2112.
Browse files Browse the repository at this point in the history
  • Loading branch information
jimfb committed Apr 7, 2015
1 parent ddbbaa9 commit 7d44917
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 287 deletions.
4 changes: 0 additions & 4 deletions src/classic/element/ReactElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,6 @@ var ReactElement = function(type, key, ref, owner, context, props) {
// Record the component responsible for creating this element.
this._owner = owner;

// TODO: Deprecate withContext, and then the context becomes accessible
// through the owner.
this._context = context;

if (__DEV__) {
// The validation flag and props are currently mutative. We put them on
// an external backing store so that we can freeze the whole object.
Expand Down
24 changes: 0 additions & 24 deletions src/classic/element/__tests__/ReactElement-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,30 +86,6 @@ describe('ReactElement', function() {
expect(element.props).toEqual({foo:'56'});
});

it('preserves the legacy context on the element', function() {
var Component = React.createFactory(ComponentClass);
var element;

var Wrapper = React.createClass({
childContextTypes: {
foo: React.PropTypes.string
},
getChildContext: function() {
return {foo: 'bar'};
},
render: function() {
element = Component();
return element;
}
});

ReactTestUtils.renderIntoDocument(
React.createElement(Wrapper)
);

expect(element._context).toEqual({foo: 'bar'});
});

it('preserves the owner on the element', function() {
var Component = React.createFactory(ComponentClass);
var element;
Expand Down
41 changes: 2 additions & 39 deletions src/core/ReactCompositeComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ var ReactCompositeComponentMixin = {
this._rootNodeID = rootID;

var publicProps = this._processProps(this._currentElement.props);
var publicContext = this._processContext(this._currentElement._context);
var publicContext = this._processContext(context);

var Component = ReactNativeComponent.getComponentClassForElement(
this._currentElement
Expand Down Expand Up @@ -158,10 +158,6 @@ var ReactCompositeComponentMixin = {
// Store a reference from the instance back to the internal representation
ReactInstanceMap.set(inst, this);

if (__DEV__) {
this._warnIfContextsDiffer(this._currentElement._context, context);
}

if (__DEV__) {
// Since plain JS classes are defined without any special initialization
// logic, we can not catch common errors early. Therefore, we have to
Expand Down Expand Up @@ -529,30 +525,6 @@ var ReactCompositeComponentMixin = {
}
},

/**
* Compare two contexts, warning if they are different
* TODO: Remove this check when owner-context is removed
*/
_warnIfContextsDiffer: function(ownerBasedContext, parentBasedContext) {
ownerBasedContext = this._maskContext(ownerBasedContext);
parentBasedContext = this._maskContext(parentBasedContext);
var parentKeys = Object.keys(parentBasedContext).sort();
var displayName = this.getName() || 'ReactCompositeComponent';
for (var i = 0; i < parentKeys.length; i++) {
var key = parentKeys[i];
warning(
ownerBasedContext[key] === parentBasedContext[key],
'owner-based and parent-based contexts differ ' +
'(values: `%s` vs `%s`) for key (%s) while mounting %s ' +
'(see: http://fb.me/react-context-by-parent)',
ownerBasedContext[key],
parentBasedContext[key],
key,
displayName
);
}
},

/**
* Perform an update to a mounted component. The componentWillReceiveProps and
* shouldComponentUpdate methods are called, then (assuming the update isn't
Expand Down Expand Up @@ -582,18 +554,9 @@ var ReactCompositeComponentMixin = {

// Distinguish between a props update versus a simple state update
if (prevParentElement !== nextParentElement) {
nextContext = this._processContext(nextParentElement._context);
nextContext = this._processContext(nextUnmaskedContext);
nextProps = this._processProps(nextParentElement.props);

if (__DEV__) {
if (nextUnmaskedContext != null) {
this._warnIfContextsDiffer(
nextParentElement._context,
nextUnmaskedContext
);
}
}

// An update here will schedule an update but immediately set
// _pendingStateQueue which will ensure that any state updates gets
// immediately reconciled instead of waiting for the next batch.
Expand Down
44 changes: 1 addition & 43 deletions src/core/ReactContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,7 @@

'use strict';

var assign = require('Object.assign');
var emptyObject = require('emptyObject');
var warning = require('warning');

var didWarn = false;

/**
* Keeps track of the current context.
Expand All @@ -29,45 +25,7 @@ var ReactContext = {
* @internal
* @type {object}
*/
current: emptyObject,

/**
* Temporarily extends the current context while executing scopedCallback.
*
* A typical use case might look like
*
* render: function() {
* var children = ReactContext.withContext({foo: 'foo'}, () => (
*
* ));
* return <div>{children}</div>;
* }
*
* @param {object} newContext New context to merge into the existing context
* @param {function} scopedCallback Callback to run with the new context
* @return {ReactComponent|array<ReactComponent>}
*/
withContext: function(newContext, scopedCallback) {
if (__DEV__) {
warning(
didWarn,
'withContext is deprecated and will be removed in a future version. ' +
'Use a wrapper component with getChildContext instead.'
);

didWarn = true;
}

var result;
var previousContext = ReactContext.current;
ReactContext.current = assign({}, previousContext, newContext);
try {
result = scopedCallback();
} finally {
ReactContext.current = previousContext;
}
return result;
}
current: emptyObject

};

Expand Down
Loading

0 comments on commit 7d44917

Please sign in to comment.