Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions src/renderers/__tests__/ReactStatelessComponent-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,43 @@ describe('ReactStatelessComponent', () => {
console.error.calls.reset();
});

// This guards against a regression caused by clearing the current debug fiber.
// https://github.com/facebook/react/issues/10831
it('should warn when giving a function ref with context', () => {
spyOn(console, 'error');

function Child() {
return null;
}
Child.contextTypes = {
foo: PropTypes.string,
};

class Parent extends React.Component {
static childContextTypes = {
foo: PropTypes.string,
};
getChildContext() {
return {
foo: 'bar',
};
}
render() {
return <Child ref={function() {}} />;
}
}

ReactTestUtils.renderIntoDocument(<Parent />);
expectDev(console.error.calls.count()).toBe(1);
expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
'Warning: Stateless function components cannot be given refs. ' +
'Attempts to access this ref will fail.\n\nCheck the render method ' +
'of `Parent`.\n' +
' in Child (at **)\n' +
' in Parent (at **)',
);
});

it('should provide a null ref', () => {
function Child() {
return <div />;
Expand Down
29 changes: 25 additions & 4 deletions src/renderers/shared/fiber/ReactFiberContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,20 @@ exports.getMaskedContext = function(

if (__DEV__) {
const name = getComponentName(workInProgress) || 'Unknown';
ReactDebugCurrentFiber.setCurrentFiber(workInProgress, null);
if (workInProgress !== ReactDebugCurrentFiber.current) {
warning(
false,
'Expected the work in progress to match the currently processed fiber. ' +
'This error is likely caused by a bug in React. Please file an issue.',
);
}
checkPropTypes(
contextTypes,
context,
'context',
name,
ReactDebugCurrentFiber.getCurrentFiberStackAddendum,
);
ReactDebugCurrentFiber.resetCurrentFiber();
}

// Cache unmasked context so we can avoid recreating masked context unless necessary.
Expand Down Expand Up @@ -184,11 +189,19 @@ function processChildContext(

let childContext;
if (__DEV__) {
// TODO: we only have to store the "previous" fiber and phase and restore them
// because this method can be called outside of reconciliation. We can remove this
// when we stop supporting unstable_renderSubtreeIntoContainer.
const previousCurrentFiber = ReactDebugCurrentFiber.current;
const previousCurrentPhase = ReactDebugCurrentFiber.phase;
ReactDebugCurrentFiber.setCurrentFiber(fiber, 'getChildContext');
startPhaseTimer(fiber, 'getChildContext');
childContext = instance.getChildContext();
stopPhaseTimer();
ReactDebugCurrentFiber.resetCurrentFiber();
ReactDebugCurrentFiber.setCurrentFiber(
previousCurrentFiber,
previousCurrentPhase,
);
} else {
childContext = instance.getChildContext();
}
Expand All @@ -208,6 +221,11 @@ function processChildContext(
// assume anything about the given fiber. We won't pass it down if we aren't sure.
// TODO: remove this hack when we delete unstable_renderSubtree in Fiber.
const workInProgress = isReconciling ? fiber : null;
// TODO: we only have to store the "previous" fiber and phase and restore them
// because this method can be called outside of reconciliation. We can remove this
// when we stop supporting unstable_renderSubtreeIntoContainer.
const previousCurrentFiber = ReactDebugCurrentFiber.current;
const previousCurrentPhase = ReactDebugCurrentFiber.phase;
ReactDebugCurrentFiber.setCurrentFiber(workInProgress, null);
checkPropTypes(
childContextTypes,
Expand All @@ -216,7 +234,10 @@ function processChildContext(
name,
ReactDebugCurrentFiber.getCurrentFiberStackAddendum,
);
ReactDebugCurrentFiber.resetCurrentFiber();
ReactDebugCurrentFiber.setCurrentFiber(
previousCurrentFiber,
previousCurrentPhase,
);
}

return {...parentContext, ...childContext};
Expand Down