Skip to content

Commit

Permalink
Also disable it on the server is flag is on
Browse files Browse the repository at this point in the history
  • Loading branch information
gaearon committed Aug 1, 2019
1 parent 4387c96 commit 4250fe8
Show file tree
Hide file tree
Showing 3 changed files with 218 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @emails react-core
*/

'use strict';

const ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');

let React;
let ReactDOM;
let ReactFeatureFlags;
let ReactDOMServer;
let ReactTestUtils;

function initModules() {
// Reset warning cache.
jest.resetModuleRegistry();
React = require('react');
ReactDOM = require('react-dom');
ReactDOMServer = require('react-dom/server');
ReactTestUtils = require('react-dom/test-utils');

ReactFeatureFlags = require('shared/ReactFeatureFlags');
ReactFeatureFlags.disableLegacyContext = true;

// Make them available to the helpers.
return {
ReactDOM,
ReactDOMServer,
ReactTestUtils,
};
}

const {resetModules, itRenders} = ReactDOMServerIntegrationUtils(initModules);

describe('ReactDOMServerIntegrationLegacyContextDisabled', () => {
beforeEach(() => {
resetModules();
});

itRenders('undefined legacy context with warning', async render => {
class LegacyProvider extends React.Component {
static childContextTypes = {
foo() {},
};
getChildContext() {
return {foo: 10};
}
render() {
return this.props.children;
}
}

let lifecycleContextLog = [];
class LegacyClsConsumer extends React.Component {
static contextTypes = {
foo() {},
};
shouldComponentUpdate(nextProps, nextState, nextContext) {
lifecycleContextLog.push(nextContext);
return true;
}
UNSAFE_componentWillReceiveProps(nextProps, nextContext) {
lifecycleContextLog.push(nextContext);
}
UNSAFE_componentWillUpdate(nextProps, nextState, nextContext) {
lifecycleContextLog.push(nextContext);
}
render() {
return typeof this.context;
}
}

function LegacyFnConsumer(props, context) {
return typeof context;
}
LegacyFnConsumer.contextTypes = {foo() {}};

function RegularFn(props, context) {
return typeof context;
}

const e = await render(
<LegacyProvider>
<span>
<LegacyClsConsumer />
<LegacyFnConsumer />
<RegularFn />
</span>
</LegacyProvider>,
3,
);
expect(e.textContent).toBe('undefinedundefinedundefined');
expect(lifecycleContextLog).toEqual([]);
});

itRenders('modern context', async render => {
let Ctx = React.createContext();

class Provider extends React.Component {
render() {
return (
<Ctx.Provider value={this.props.value}>
{this.props.children}
</Ctx.Provider>
);
}
}

class RenderPropConsumer extends React.Component {
render() {
return <Ctx.Consumer>{value => value}</Ctx.Consumer>;
}
}

let lifecycleContextLog = [];
class ContextTypeConsumer extends React.Component {
static contextType = Ctx;
shouldComponentUpdate(nextProps, nextState, nextContext) {
lifecycleContextLog.push(nextContext);
return true;
}
UNSAFE_componentWillReceiveProps(nextProps, nextContext) {
lifecycleContextLog.push(nextContext);
}
UNSAFE_componentWillUpdate(nextProps, nextState, nextContext) {
lifecycleContextLog.push(nextContext);
}
render() {
return this.context;
}
}

function FnConsumer() {
return React.useContext(Ctx);
}

const e = await render(
<Provider value="a">
<span>
<RenderPropConsumer />
<ContextTypeConsumer />
<FnConsumer />
</span>
</Provider>,
);
expect(e.textContent).toBe('aaa');
expect(lifecycleContextLog).toEqual([]);
});
});
53 changes: 34 additions & 19 deletions packages/react-dom/src/server/ReactPartialRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import describeComponentFrame from 'shared/describeComponentFrame';
import ReactSharedInternals from 'shared/ReactSharedInternals';
import {
warnAboutDeprecatedLifecycles,
disableLegacyContext,
enableSuspenseServerRenderer,
enableFundamentalAPI,
enableFlareAPI,
Expand Down Expand Up @@ -650,29 +651,43 @@ function resolve(
validateRenderResult(child, Component);

let childContext;
if (typeof inst.getChildContext === 'function') {
let childContextTypes = Component.childContextTypes;
if (typeof childContextTypes === 'object') {
childContext = inst.getChildContext();
for (let contextKey in childContext) {
invariant(
contextKey in childContextTypes,
'%s.getChildContext(): key "%s" is not defined in childContextTypes.',
if (disableLegacyContext) {
if (__DEV__) {
let childContextTypes = Component.childContextTypes;
if (childContextTypes !== undefined) {
warningWithoutStack(
false,
'%s uses the legacy childContextTypes API which is no longer supported. ' +
'Use React.createContext() instead.',
getComponentName(Component) || 'Unknown',
contextKey,
);
}
} else {
warningWithoutStack(
false,
'%s.getChildContext(): childContextTypes must be defined in order to ' +
'use getChildContext().',
getComponentName(Component) || 'Unknown',
);
}
}
if (childContext) {
context = Object.assign({}, context, childContext);
} else {
if (typeof inst.getChildContext === 'function') {
let childContextTypes = Component.childContextTypes;
if (typeof childContextTypes === 'object') {
childContext = inst.getChildContext();
for (let contextKey in childContext) {
invariant(
contextKey in childContextTypes,
'%s.getChildContext(): key "%s" is not defined in childContextTypes.',
getComponentName(Component) || 'Unknown',
contextKey,
);
}
} else {
warningWithoutStack(
false,
'%s.getChildContext(): childContextTypes must be defined in order to ' +
'use getChildContext().',
getComponentName(Component) || 'Unknown',
);
}
}
if (childContext) {
context = Object.assign({}, context, childContext);
}
}
}
return {child, context};
Expand Down
34 changes: 29 additions & 5 deletions packages/react-dom/src/server/ReactPartialRendererContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import type {ThreadID} from './ReactThreadIDAllocator';
import type {ReactContext} from 'shared/ReactTypes';

import {disableLegacyContext} from 'shared/ReactFeatureFlags';
import {REACT_CONTEXT_TYPE, REACT_PROVIDER_TYPE} from 'shared/ReactSymbols';
import ReactSharedInternals from 'shared/ReactSharedInternals';
import getComponentName from 'shared/getComponentName';
Expand Down Expand Up @@ -121,12 +122,35 @@ export function processContext(
validateContextBounds(contextType, threadID);
return contextType[threadID];
} else {
const maskedContext = maskContext(type, context);
if (__DEV__) {
if (type.contextTypes) {
checkContextTypes(type.contextTypes, maskedContext, 'context');
if (disableLegacyContext) {
if (__DEV__) {
if (type.contextTypes) {
if (type.prototype && type.prototype.isReactComponent) {
warningWithoutStack(
false,
'%s uses the legacy contextTypes API which is no longer supported. ' +
'Use React.createContext() with static contextType instead.',
getComponentName(type) || 'Unknown',
);
} else {
warningWithoutStack(
false,
'%s uses the legacy contextTypes API which is no longer supported. ' +
'Use React.createContext() with React.useContext() instead.',
getComponentName(type) || 'Unknown',
);
}
}
}
return undefined;
} else {
const maskedContext = maskContext(type, context);
if (__DEV__) {
if (type.contextTypes) {
checkContextTypes(type.contextTypes, maskedContext, 'context');
}
}
return maskedContext;
}
return maskedContext;
}
}

0 comments on commit 4250fe8

Please sign in to comment.