Skip to content

Commit 093cc1a

Browse files
committed
Add Server Context deprecation warning
1 parent bff6be8 commit 093cc1a

File tree

5 files changed

+120
-36
lines changed

5 files changed

+120
-36
lines changed

packages/react-client/src/__tests__/ReactFlight-test.js

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,19 @@ describe('ReactFlight', () => {
9898
jest.restoreAllMocks();
9999
});
100100

101+
function createServerContext(globalName, defaultValue, withStack) {
102+
let ctx;
103+
expect(() => {
104+
ctx = React.createServerContext(globalName, defaultValue);
105+
}).toErrorDev(
106+
'Server Context is deprecated and will soon be removed. ' +
107+
'It was never documented and we have found it not to be useful ' +
108+
'enough to warrant the downside it emposes on all apps.',
109+
{withoutStack: !withStack},
110+
);
111+
return ctx;
112+
}
113+
101114
function clientReference(value) {
102115
return Object.defineProperties(
103116
function () {
@@ -1063,7 +1076,7 @@ describe('ReactFlight', () => {
10631076
describe('ServerContext', () => {
10641077
// @gate enableServerContext
10651078
it('supports basic createServerContext usage', async () => {
1066-
const ServerContext = React.createServerContext(
1079+
const ServerContext = createServerContext(
10671080
'ServerContext',
10681081
'hello from server',
10691082
);
@@ -1084,10 +1097,7 @@ describe('ReactFlight', () => {
10841097

10851098
// @gate enableServerContext
10861099
it('propagates ServerContext providers in flight', async () => {
1087-
const ServerContext = React.createServerContext(
1088-
'ServerContext',
1089-
'default',
1090-
);
1100+
const ServerContext = createServerContext('ServerContext', 'default');
10911101

10921102
function Foo() {
10931103
return (
@@ -1115,7 +1125,7 @@ describe('ReactFlight', () => {
11151125

11161126
// @gate enableServerContext
11171127
it('errors if you try passing JSX through ServerContext value', () => {
1118-
const ServerContext = React.createServerContext('ServerContext', {
1128+
const ServerContext = createServerContext('ServerContext', {
11191129
foo: {
11201130
bar: <span>hi this is default</span>,
11211131
},
@@ -1149,10 +1159,7 @@ describe('ReactFlight', () => {
11491159

11501160
// @gate enableServerContext
11511161
it('propagates ServerContext and cleans up the providers in flight', async () => {
1152-
const ServerContext = React.createServerContext(
1153-
'ServerContext',
1154-
'default',
1155-
);
1162+
const ServerContext = createServerContext('ServerContext', 'default');
11561163

11571164
function Foo() {
11581165
return (
@@ -1196,10 +1203,7 @@ describe('ReactFlight', () => {
11961203

11971204
// @gate enableServerContext
11981205
it('propagates ServerContext providers in flight after suspending', async () => {
1199-
const ServerContext = React.createServerContext(
1200-
'ServerContext',
1201-
'default',
1202-
);
1206+
const ServerContext = createServerContext('ServerContext', 'default');
12031207

12041208
function Foo() {
12051209
return (
@@ -1254,10 +1258,7 @@ describe('ReactFlight', () => {
12541258

12551259
// @gate enableServerContext
12561260
it('serializes ServerContext to client', async () => {
1257-
const ServerContext = React.createServerContext(
1258-
'ServerContext',
1259-
'default',
1260-
);
1261+
const ServerContext = createServerContext('ServerContext', 'default');
12611262

12621263
function ClientBar() {
12631264
Scheduler.log('ClientBar');
@@ -1294,16 +1295,13 @@ describe('ReactFlight', () => {
12941295
expect(ReactNoop).toMatchRenderedOutput(<span>hi this is server</span>);
12951296

12961297
expect(() => {
1297-
React.createServerContext('ServerContext', 'default');
1298+
createServerContext('ServerContext', 'default');
12981299
}).toThrow('ServerContext: ServerContext already defined');
12991300
});
13001301

13011302
// @gate enableServerContext
13021303
it('takes ServerContext from the client for refetching use cases', async () => {
1303-
const ServerContext = React.createServerContext(
1304-
'ServerContext',
1305-
'default',
1306-
);
1304+
const ServerContext = createServerContext('ServerContext', 'default');
13071305
function Bar() {
13081306
return <span>{React.useContext(ServerContext)}</span>;
13091307
}
@@ -1323,15 +1321,15 @@ describe('ReactFlight', () => {
13231321
let ServerContext;
13241322
function inlineLazyServerContextInitialization() {
13251323
if (!ServerContext) {
1326-
ServerContext = React.createServerContext('ServerContext', 'default');
1324+
ServerContext = createServerContext('ServerContext', 'default');
13271325
}
13281326
return ServerContext;
13291327
}
13301328

13311329
let ClientContext;
13321330
function inlineContextInitialization() {
13331331
if (!ClientContext) {
1334-
ClientContext = React.createServerContext('ServerContext', 'default');
1332+
ClientContext = createServerContext('ServerContext', 'default', true);
13351333
}
13361334
return ClientContext;
13371335
}

packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3321,7 +3321,16 @@ describe('ReactDOMFizzServer', () => {
33213321
let ServerContext;
33223322
function inlineLazyServerContextInitialization() {
33233323
if (!ServerContext) {
3324-
ServerContext = React.createServerContext('ServerContext', 'default');
3324+
expect(() => {
3325+
ServerContext = React.createServerContext('ServerContext', 'default');
3326+
}).toErrorDev(
3327+
'Server Context is deprecated and will soon be removed. ' +
3328+
'It was never documented and we have found it not to be useful ' +
3329+
'enough to warrant the downside it emposes on all apps.',
3330+
{
3331+
withoutStack: true,
3332+
},
3333+
);
33253334
}
33263335
return ServerContext;
33273336
}
@@ -5604,7 +5613,15 @@ describe('ReactDOMFizzServer', () => {
56045613
it('basic use(context)', async () => {
56055614
const ContextA = React.createContext('default');
56065615
const ContextB = React.createContext('B');
5607-
const ServerContext = React.createServerContext('ServerContext', 'default');
5616+
let ServerContext;
5617+
expect(() => {
5618+
ServerContext = React.createServerContext('ServerContext', 'default');
5619+
}).toErrorDev(
5620+
'Server Context is deprecated and will soon be removed. ' +
5621+
'It was never documented and we have found it not to be useful ' +
5622+
'enough to warrant the downside it emposes on all apps.',
5623+
{withoutStack: true},
5624+
);
56085625
function Client() {
56095626
return use(ContextA) + use(ContextB);
56105627
}

packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -609,8 +609,22 @@ describe('ReactFlightDOMBrowser', () => {
609609
});
610610

611611
it('basic use(context)', async () => {
612-
const ContextA = React.createServerContext('ContextA', '');
613-
const ContextB = React.createServerContext('ContextB', 'B');
612+
let ContextA;
613+
let ContextB;
614+
expect(() => {
615+
ContextA = React.createServerContext('ContextA', '');
616+
ContextB = React.createServerContext('ContextB', 'B');
617+
}).toErrorDev(
618+
[
619+
'Server Context is deprecated and will soon be removed. ' +
620+
'It was never documented and we have found it not to be useful ' +
621+
'enough to warrant the downside it emposes on all apps.',
622+
'Server Context is deprecated and will soon be removed. ' +
623+
'It was never documented and we have found it not to be useful ' +
624+
'enough to warrant the downside it emposes on all apps.',
625+
],
626+
{withoutStack: true},
627+
);
614628

615629
function ServerComponent() {
616630
return use(ContextA) + use(ContextB);

packages/react/src/ReactServerContext.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ export function createServerContext<T: ServerContextJSONValue>(
3030
if (!enableServerContext) {
3131
throw new Error('Not implemented.');
3232
}
33+
if (__DEV__) {
34+
console.error(
35+
'Server Context is deprecated and will soon be removed. ' +
36+
'It was never documented and we have found it not to be useful ' +
37+
'enough to warrant the downside it emposes on all apps.',
38+
);
39+
}
3340
let wasDefined = true;
3441
if (!ContextRegistry[globalName]) {
3542
wasDefined = false;

packages/shared/ReactServerContextRegistry.js

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,69 @@
99

1010
import type {ReactServerContext} from 'shared/ReactTypes';
1111

12-
import {REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED} from 'shared/ReactSymbols';
12+
import {
13+
REACT_PROVIDER_TYPE,
14+
REACT_SERVER_CONTEXT_TYPE,
15+
REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED,
16+
} from 'shared/ReactSymbols';
17+
1318
import ReactSharedInternals from 'shared/ReactSharedInternals';
14-
import {createServerContext} from 'react';
1519

1620
const ContextRegistry = ReactSharedInternals.ContextRegistry;
1721

1822
export function getOrCreateServerContext(
1923
globalName: string,
2024
): ReactServerContext<any> {
2125
if (!ContextRegistry[globalName]) {
22-
ContextRegistry[globalName] = createServerContext(
23-
globalName,
24-
// $FlowFixMe[incompatible-call] function signature doesn't reflect the symbol value
25-
REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED,
26-
);
26+
const context: ReactServerContext<any> = {
27+
$$typeof: REACT_SERVER_CONTEXT_TYPE,
28+
29+
// As a workaround to support multiple concurrent renderers, we categorize
30+
// some renderers as primary and others as secondary. We only expect
31+
// there to be two concurrent renderers at most: React Native (primary) and
32+
// Fabric (secondary); React DOM (primary) and React ART (secondary).
33+
// Secondary renderers store their context values on separate fields.
34+
_currentValue: REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED,
35+
_currentValue2: REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED,
36+
37+
_defaultValue: REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED,
38+
39+
// Used to track how many concurrent renderers this context currently
40+
// supports within in a single renderer. Such as parallel server rendering.
41+
_threadCount: 0,
42+
// These are circular
43+
Provider: (null: any),
44+
Consumer: (null: any),
45+
_globalName: globalName,
46+
};
47+
48+
context.Provider = {
49+
$$typeof: REACT_PROVIDER_TYPE,
50+
_context: context,
51+
};
52+
53+
if (__DEV__) {
54+
let hasWarnedAboutUsingConsumer;
55+
context._currentRenderer = null;
56+
context._currentRenderer2 = null;
57+
Object.defineProperties(
58+
context,
59+
({
60+
Consumer: {
61+
get() {
62+
if (!hasWarnedAboutUsingConsumer) {
63+
console.error(
64+
'Consumer pattern is not supported by ReactServerContext',
65+
);
66+
hasWarnedAboutUsingConsumer = true;
67+
}
68+
return null;
69+
},
70+
},
71+
}: any),
72+
);
73+
}
74+
ContextRegistry[globalName] = context;
2775
}
2876
return ContextRegistry[globalName];
2977
}

0 commit comments

Comments
 (0)