Show deprecated context object warnings usage in ReactDOM server (#14033)
* Applies context object warnings to ReactDOM server
This commit is contained in:
parent
e3a7b96455
commit
aa1ffe4e77
|
@ -249,5 +249,104 @@ describe('ReactDOMServerIntegration', () => {
|
|||
expect(e.querySelector('#language2').textContent).toBe('sanskrit');
|
||||
expect(e.querySelector('#language3').textContent).toBe('french');
|
||||
});
|
||||
|
||||
itRenders(
|
||||
'should warn with an error message when using Context as consumer in DEV',
|
||||
async render => {
|
||||
const Theme = React.createContext('dark');
|
||||
const Language = React.createContext('french');
|
||||
|
||||
const App = () => (
|
||||
<div>
|
||||
<Theme.Provider value="light">
|
||||
<Language.Provider value="english">
|
||||
<Theme.Provider value="dark">
|
||||
<Theme>{theme => <div id="theme1">{theme}</div>}</Theme>
|
||||
</Theme.Provider>
|
||||
</Language.Provider>
|
||||
</Theme.Provider>
|
||||
</div>
|
||||
);
|
||||
// We expect 1 error.
|
||||
await render(<App />, 1);
|
||||
},
|
||||
);
|
||||
|
||||
// False positive regression test.
|
||||
itRenders(
|
||||
'should not warn when using Consumer from React < 16.6 with newer renderer',
|
||||
async render => {
|
||||
const Theme = React.createContext('dark');
|
||||
const Language = React.createContext('french');
|
||||
// React 16.5 and earlier didn't have a separate object.
|
||||
Theme.Consumer = Theme;
|
||||
|
||||
const App = () => (
|
||||
<div>
|
||||
<Theme.Provider value="light">
|
||||
<Language.Provider value="english">
|
||||
<Theme.Provider value="dark">
|
||||
<Theme>{theme => <div id="theme1">{theme}</div>}</Theme>
|
||||
</Theme.Provider>
|
||||
</Language.Provider>
|
||||
</Theme.Provider>
|
||||
</div>
|
||||
);
|
||||
// We expect 0 errors.
|
||||
await render(<App />, 0);
|
||||
},
|
||||
);
|
||||
|
||||
itRenders(
|
||||
'should warn with an error message when using nested context consumers in DEV',
|
||||
async render => {
|
||||
const App = () => {
|
||||
const Theme = React.createContext('dark');
|
||||
const Language = React.createContext('french');
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Theme.Provider value="light">
|
||||
<Language.Provider value="english">
|
||||
<Theme.Provider value="dark">
|
||||
<Theme.Consumer.Consumer>
|
||||
{theme => <div id="theme1">{theme}</div>}
|
||||
</Theme.Consumer.Consumer>
|
||||
</Theme.Provider>
|
||||
</Language.Provider>
|
||||
</Theme.Provider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
// We expect 1 error.
|
||||
await render(<App />, 1);
|
||||
},
|
||||
);
|
||||
|
||||
itRenders(
|
||||
'should warn with an error message when using Context.Consumer.Provider DEV',
|
||||
async render => {
|
||||
const App = () => {
|
||||
const Theme = React.createContext('dark');
|
||||
const Language = React.createContext('french');
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Theme.Provider value="light">
|
||||
<Language.Provider value="english">
|
||||
<Theme.Consumer.Provider value="dark">
|
||||
<Theme.Consumer>
|
||||
{theme => <div id="theme1">{theme}</div>}
|
||||
</Theme.Consumer>
|
||||
</Theme.Consumer.Provider>
|
||||
</Language.Provider>
|
||||
</Theme.Provider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
// We expect 1 error.
|
||||
await render(<App />, 1);
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,11 +8,7 @@
|
|||
*/
|
||||
|
||||
import type {ReactElement} from 'shared/ReactElementType';
|
||||
import type {
|
||||
ReactProvider,
|
||||
ReactConsumer,
|
||||
ReactContext,
|
||||
} from 'shared/ReactTypes';
|
||||
import type {ReactProvider, ReactContext} from 'shared/ReactTypes';
|
||||
|
||||
import React from 'react';
|
||||
import invariant from 'shared/invariant';
|
||||
|
@ -93,6 +89,7 @@ let validatePropertiesInDevelopment = (type, props) => {};
|
|||
let pushCurrentDebugStack = (stack: Array<Frame>) => {};
|
||||
let pushElementToDebugStack = (element: ReactElement) => {};
|
||||
let popCurrentDebugStack = () => {};
|
||||
let hasWarnedAboutUsingContextAsConsumer = false;
|
||||
|
||||
if (__DEV__) {
|
||||
ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
|
||||
|
@ -1061,9 +1058,35 @@ class ReactDOMServerRenderer {
|
|||
return '';
|
||||
}
|
||||
case REACT_CONTEXT_TYPE: {
|
||||
const consumer: ReactConsumer<any> = (nextChild: any);
|
||||
const nextProps: any = consumer.props;
|
||||
const nextValue = consumer.type._currentValue;
|
||||
let reactContext = (nextChild: any).type;
|
||||
// The logic below for Context differs depending on PROD or DEV mode. In
|
||||
// DEV mode, we create a separate object for Context.Consumer that acts
|
||||
// like a proxy to Context. This proxy object adds unnecessary code in PROD
|
||||
// so we use the old behaviour (Context.Consumer references Context) to
|
||||
// reduce size and overhead. The separate object references context via
|
||||
// a property called "_context", which also gives us the ability to check
|
||||
// in DEV mode if this property exists or not and warn if it does not.
|
||||
if (__DEV__) {
|
||||
if ((reactContext: any)._context === undefined) {
|
||||
// This may be because it's a Context (rather than a Consumer).
|
||||
// Or it may be because it's older React where they're the same thing.
|
||||
// We only want to warn if we're sure it's a new React.
|
||||
if (reactContext !== reactContext.Consumer) {
|
||||
if (!hasWarnedAboutUsingContextAsConsumer) {
|
||||
hasWarnedAboutUsingContextAsConsumer = true;
|
||||
warning(
|
||||
false,
|
||||
'Rendering <Context> directly is not supported and will be removed in ' +
|
||||
'a future major release. Did you mean to render <Context.Consumer> instead?',
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reactContext = (reactContext: any)._context;
|
||||
}
|
||||
}
|
||||
const nextProps: any = (nextChild: any).props;
|
||||
const nextValue = reactContext._currentValue;
|
||||
|
||||
const nextChildren = toArray(nextProps.children(nextValue));
|
||||
const frame: Frame = {
|
||||
|
|
Loading…
Reference in New Issue