Files
react/packages/shared/ReactServerContextRegistry.js
Sebastian Markbåge 1ebedbec2b Add Server Context deprecation warning (#27424)
As agreed, we're removing Server Context. This was never official
documented.

We've found that it's not that useful in practice. Often the better
options are:

- Read things off the url or global scope like params or cookies.
- Use the module system for global dependency injection.
- Use `React.cache()` to dedupe multiple things instead of computing
once and passing down.

There are still legit use cases for Server Context but you have to be
very careful not to pass any large data, so in generally we recommend
against it anyway.

Yes, prop drilling is annoying but it's not impossible for the cases
this is needed. I would personally always pick it over Server Context
anyway.

Semantically, Server Context also blocks object deduping due to how it
plays out with Server Components that can't be deduped. This is much
more important feature.

Since it's already in canary along with the rest of RSC, we're adding a
warning for a few versions before removing completely to help migration.

---------

Co-authored-by: Josh Story <josh.c.story@gmail.com>
2023-09-28 11:03:19 -04:00

78 lines
2.4 KiB
JavaScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
import type {ReactServerContext} from 'shared/ReactTypes';
import {
REACT_PROVIDER_TYPE,
REACT_SERVER_CONTEXT_TYPE,
REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED,
} from 'shared/ReactSymbols';
import ReactSharedInternals from 'shared/ReactSharedInternals';
const ContextRegistry = ReactSharedInternals.ContextRegistry;
export function getOrCreateServerContext(
globalName: string,
): ReactServerContext<any> {
if (!ContextRegistry[globalName]) {
const context: ReactServerContext<any> = {
$$typeof: REACT_SERVER_CONTEXT_TYPE,
// As a workaround to support multiple concurrent renderers, we categorize
// some renderers as primary and others as secondary. We only expect
// there to be two concurrent renderers at most: React Native (primary) and
// Fabric (secondary); React DOM (primary) and React ART (secondary).
// Secondary renderers store their context values on separate fields.
_currentValue: REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED,
_currentValue2: REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED,
_defaultValue: REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED,
// Used to track how many concurrent renderers this context currently
// supports within in a single renderer. Such as parallel server rendering.
_threadCount: 0,
// These are circular
Provider: (null: any),
Consumer: (null: any),
_globalName: globalName,
};
context.Provider = {
$$typeof: REACT_PROVIDER_TYPE,
_context: context,
};
if (__DEV__) {
let hasWarnedAboutUsingConsumer;
context._currentRenderer = null;
context._currentRenderer2 = null;
Object.defineProperties(
context,
({
Consumer: {
get() {
if (!hasWarnedAboutUsingConsumer) {
console.error(
'Consumer pattern is not supported by ReactServerContext',
);
hasWarnedAboutUsingConsumer = true;
}
return null;
},
},
}: any),
);
}
ContextRegistry[globalName] = context;
}
return ContextRegistry[globalName];
}