diff --git a/packages/react-art/src/ReactART.js b/packages/react-art/src/ReactART.js
index a29f9cd23714d..9d1b6a16c2038 100644
--- a/packages/react-art/src/ReactART.js
+++ b/packages/react-art/src/ReactART.js
@@ -66,7 +66,15 @@ class Surface extends React.Component {
this._surface = Mode.Surface(+width, +height, this._tagRef);
- this._mountNode = createContainer(this._surface, LegacyRoot, false, null);
+ this._mountNode = createContainer(
+ this._surface,
+ LegacyRoot,
+ false,
+ null,
+ false,
+ false,
+ '',
+ );
updateContainer(this.props.children, this._mountNode, this);
}
diff --git a/packages/react-dom/src/__tests__/ReactDOMUseId-test.js b/packages/react-dom/src/__tests__/ReactDOMUseId-test.js
index dd7bbaa8b41fa..036c138d5e97a 100644
--- a/packages/react-dom/src/__tests__/ReactDOMUseId-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMUseId-test.js
@@ -94,7 +94,7 @@ describe('useId', () => {
function normalizeTreeIdForTesting(id) {
const [serverClientPrefix, base32, hookIndex] = id.split(':');
- if (serverClientPrefix === 'r') {
+ if (serverClientPrefix.endsWith('r')) {
// Client ids aren't stable. For testing purposes, strip out the counter.
return (
'CLIENT_GENERATED_ID' +
@@ -569,4 +569,66 @@ describe('useId', () => {
// Should have hydrated successfully
expect(span.current).toBe(dehydratedSpan);
});
+
+ test('identifierPrefix option', async () => {
+ function Child() {
+ const id = useId();
+ return
{id}
;
+ }
+
+ function App({showMore}) {
+ return (
+ <>
+
+
+ {showMore && }
+ >
+ );
+ }
+
+ await serverAct(async () => {
+ const {pipe} = ReactDOMFizzServer.renderToPipeableStream(, {
+ identifierPrefix: 'custom-prefix-',
+ });
+ pipe(writable);
+ });
+ let root;
+ await clientAct(async () => {
+ root = ReactDOM.hydrateRoot(container, , {
+ identifierPrefix: 'custom-prefix-',
+ });
+ });
+ expect(container).toMatchInlineSnapshot(`
+
+
+ custom-prefix-R:1
+
+
+ custom-prefix-R:2
+
+
+ `);
+
+ // Mount a new, client-only id
+ await clientAct(async () => {
+ root.render();
+ });
+ expect(container).toMatchInlineSnapshot(`
+
+
+ custom-prefix-R:1
+
+
+ custom-prefix-R:2
+
+
+ custom-prefix-r:0
+
+
+ `);
+ });
});
diff --git a/packages/react-dom/src/client/ReactDOMLegacy.js b/packages/react-dom/src/client/ReactDOMLegacy.js
index ac12f18bee509..e3def8459e754 100644
--- a/packages/react-dom/src/client/ReactDOMLegacy.js
+++ b/packages/react-dom/src/client/ReactDOMLegacy.js
@@ -121,6 +121,7 @@ function legacyCreateRootFromDOMContainer(
null, // hydrationCallbacks
false, // isStrictMode
false, // concurrentUpdatesByDefaultOverride,
+ '', // identiferPrefix
);
markContainerAsRoot(root.current, container);
diff --git a/packages/react-dom/src/client/ReactDOMRoot.js b/packages/react-dom/src/client/ReactDOMRoot.js
index d8794eec5bb1b..3c49a15fc14dc 100644
--- a/packages/react-dom/src/client/ReactDOMRoot.js
+++ b/packages/react-dom/src/client/ReactDOMRoot.js
@@ -32,6 +32,7 @@ export type CreateRootOptions = {
// END OF TODO
unstable_strictMode?: boolean,
unstable_concurrentUpdatesByDefault?: boolean,
+ identifierPrefix?: string,
...
};
@@ -43,6 +44,7 @@ export type HydrateRootOptions = {
// Options for all roots
unstable_strictMode?: boolean,
unstable_concurrentUpdatesByDefault?: boolean,
+ identifierPrefix?: string,
...
};
@@ -158,13 +160,22 @@ export function createRoot(
null;
// END TODO
- const isStrictMode = options != null && options.unstable_strictMode === true;
- let concurrentUpdatesByDefaultOverride = null;
- if (allowConcurrentByDefault) {
- concurrentUpdatesByDefaultOverride =
- options != null && options.unstable_concurrentUpdatesByDefault != null
- ? options.unstable_concurrentUpdatesByDefault
- : null;
+ let isStrictMode = false;
+ let concurrentUpdatesByDefaultOverride = false;
+ let identifierPrefix = '';
+ if (options !== null && options !== undefined) {
+ if (options.unstable_strictMode === true) {
+ isStrictMode = true;
+ }
+ if (
+ allowConcurrentByDefault &&
+ options.unstable_concurrentUpdatesByDefault === true
+ ) {
+ concurrentUpdatesByDefaultOverride = true;
+ }
+ if (options.identifierPrefix !== undefined) {
+ identifierPrefix = options.identifierPrefix;
+ }
}
const root = createContainer(
@@ -174,6 +185,7 @@ export function createRoot(
hydrationCallbacks,
isStrictMode,
concurrentUpdatesByDefaultOverride,
+ identifierPrefix,
);
markContainerAsRoot(root.current, container);
@@ -217,15 +229,25 @@ export function hydrateRoot(
// For now we reuse the whole bag of options since they contain
// the hydration callbacks.
const hydrationCallbacks = options != null ? options : null;
+ // TODO: Delete this option
const mutableSources = (options != null && options.hydratedSources) || null;
- const isStrictMode = options != null && options.unstable_strictMode === true;
-
- let concurrentUpdatesByDefaultOverride = null;
- if (allowConcurrentByDefault) {
- concurrentUpdatesByDefaultOverride =
- options != null && options.unstable_concurrentUpdatesByDefault != null
- ? options.unstable_concurrentUpdatesByDefault
- : null;
+
+ let isStrictMode = false;
+ let concurrentUpdatesByDefaultOverride = false;
+ let identifierPrefix = '';
+ if (options !== null && options !== undefined) {
+ if (options.unstable_strictMode === true) {
+ isStrictMode = true;
+ }
+ if (
+ allowConcurrentByDefault &&
+ options.unstable_concurrentUpdatesByDefault === true
+ ) {
+ concurrentUpdatesByDefaultOverride = true;
+ }
+ if (options.identifierPrefix !== undefined) {
+ identifierPrefix = options.identifierPrefix;
+ }
}
const root = createContainer(
@@ -235,6 +257,7 @@ export function hydrateRoot(
hydrationCallbacks,
isStrictMode,
concurrentUpdatesByDefaultOverride,
+ identifierPrefix,
);
markContainerAsRoot(root.current, container);
// This can't be a comment node since hydration doesn't work on comment nodes anyway.
diff --git a/packages/react-dom/src/server/ReactDOMServerFormatConfig.js b/packages/react-dom/src/server/ReactDOMServerFormatConfig.js
index 65a10974b0196..c4f8d89a8c907 100644
--- a/packages/react-dom/src/server/ReactDOMServerFormatConfig.js
+++ b/packages/react-dom/src/server/ReactDOMServerFormatConfig.js
@@ -64,6 +64,7 @@ export type ResponseState = {
placeholderPrefix: PrecomputedChunk,
segmentPrefix: PrecomputedChunk,
boundaryPrefix: string,
+ idPrefix: string,
nextSuspenseID: number,
sentCompleteSegmentFunction: boolean,
sentCompleteBoundaryFunction: boolean,
@@ -125,6 +126,7 @@ export function createResponseState(
placeholderPrefix: stringToPrecomputedChunk(idPrefix + 'P:'),
segmentPrefix: stringToPrecomputedChunk(idPrefix + 'S:'),
boundaryPrefix: idPrefix + 'B:',
+ idPrefix: idPrefix + 'R:',
nextSuspenseID: 0,
sentCompleteSegmentFunction: false,
sentCompleteBoundaryFunction: false,
@@ -229,6 +231,25 @@ export function assignSuspenseBoundaryID(
);
}
+export function makeId(
+ responseState: ResponseState,
+ treeId: string,
+ localId: number,
+): string {
+ const idPrefix = responseState.idPrefix;
+
+ let id = idPrefix + treeId;
+
+ // Unless this is the first id at this level, append a number at the end
+ // that represents the position of this useId hook among all the useId
+ // hooks for this fiber.
+ if (localId > 0) {
+ id += ':' + localId.toString(32);
+ }
+
+ return id;
+}
+
function encodeHTMLTextNode(text: string): string {
return escapeTextForBrowser(text);
}
diff --git a/packages/react-dom/src/server/ReactDOMServerLegacyFormatConfig.js b/packages/react-dom/src/server/ReactDOMServerLegacyFormatConfig.js
index 5b0798b737129..c3d09f481fb62 100644
--- a/packages/react-dom/src/server/ReactDOMServerLegacyFormatConfig.js
+++ b/packages/react-dom/src/server/ReactDOMServerLegacyFormatConfig.js
@@ -34,6 +34,7 @@ export type ResponseState = {
placeholderPrefix: PrecomputedChunk,
segmentPrefix: PrecomputedChunk,
boundaryPrefix: string,
+ idPrefix: string,
nextSuspenseID: number,
sentCompleteSegmentFunction: boolean,
sentCompleteBoundaryFunction: boolean,
@@ -54,6 +55,7 @@ export function createResponseState(
placeholderPrefix: responseState.placeholderPrefix,
segmentPrefix: responseState.segmentPrefix,
boundaryPrefix: responseState.boundaryPrefix,
+ idPrefix: responseState.idPrefix,
nextSuspenseID: responseState.nextSuspenseID,
sentCompleteSegmentFunction: responseState.sentCompleteSegmentFunction,
sentCompleteBoundaryFunction: responseState.sentCompleteBoundaryFunction,
@@ -79,6 +81,7 @@ export {
getChildFormatContext,
UNINITIALIZED_SUSPENSE_BOUNDARY_ID,
assignSuspenseBoundaryID,
+ makeId,
pushStartInstance,
pushEndInstance,
pushStartCompletedSuspenseBoundary,
diff --git a/packages/react-native-renderer/src/ReactFabric.js b/packages/react-native-renderer/src/ReactFabric.js
index 744c1c178397f..bf7754d6099c2 100644
--- a/packages/react-native-renderer/src/ReactFabric.js
+++ b/packages/react-native-renderer/src/ReactFabric.js
@@ -213,6 +213,7 @@ function render(
null,
false,
null,
+ '',
);
roots.set(containerTag, root);
}
diff --git a/packages/react-native-renderer/src/ReactNativeRenderer.js b/packages/react-native-renderer/src/ReactNativeRenderer.js
index a60683b47b2ee..fb539d8996811 100644
--- a/packages/react-native-renderer/src/ReactNativeRenderer.js
+++ b/packages/react-native-renderer/src/ReactNativeRenderer.js
@@ -202,7 +202,15 @@ function render(
if (!root) {
// TODO (bvaughn): If we decide to keep the wrapper component,
// We could create a wrapper for containerTag as well to reduce special casing.
- root = createContainer(containerTag, LegacyRoot, false, null, false, null);
+ root = createContainer(
+ containerTag,
+ LegacyRoot,
+ false,
+ null,
+ false,
+ null,
+ '',
+ );
roots.set(containerTag, root);
}
updateContainer(element, root, null, callback);
diff --git a/packages/react-native-renderer/src/server/ReactNativeServerFormatConfig.js b/packages/react-native-renderer/src/server/ReactNativeServerFormatConfig.js
index 5b12d810bbe0f..20084731b5333 100644
--- a/packages/react-native-renderer/src/server/ReactNativeServerFormatConfig.js
+++ b/packages/react-native-renderer/src/server/ReactNativeServerFormatConfig.js
@@ -107,6 +107,14 @@ export function assignSuspenseBoundaryID(
return responseState.nextSuspenseID++;
}
+export function makeId(
+ responseState: ResponseState,
+ treeId: string,
+ localId: number,
+): string {
+ throw new Error('Not implemented');
+}
+
const RAW_TEXT = stringToPrecomputedChunk('RCTRawText');
export function pushTextInstance(
diff --git a/packages/react-noop-renderer/src/createReactNoop.js b/packages/react-noop-renderer/src/createReactNoop.js
index c5021d968939d..ef76b6610617f 100644
--- a/packages/react-noop-renderer/src/createReactNoop.js
+++ b/packages/react-noop-renderer/src/createReactNoop.js
@@ -973,6 +973,8 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
false,
null,
null,
+ false,
+ '',
);
return {
_Scheduler: Scheduler,
@@ -1000,6 +1002,8 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
false,
null,
null,
+ false,
+ '',
);
return {
_Scheduler: Scheduler,
diff --git a/packages/react-reconciler/src/ReactFiberHooks.new.js b/packages/react-reconciler/src/ReactFiberHooks.new.js
index 2ea341864642c..2c26859bafe70 100644
--- a/packages/react-reconciler/src/ReactFiberHooks.new.js
+++ b/packages/react-reconciler/src/ReactFiberHooks.new.js
@@ -2035,12 +2035,20 @@ export function getIsUpdatingOpaqueValueInRenderPhaseInDEV(): boolean | void {
function mountId(): string {
const hook = mountWorkInProgressHook();
+ const root = ((getWorkInProgressRoot(): any): FiberRoot);
+ // TODO: In Fizz, id generation is specific to each server config. Maybe we
+ // should do this in Fiber, too? Deferring this decision for now because
+ // there's no other place to store the prefix except for an internal field on
+ // the public createRoot object, which the fiber tree does not currently have
+ // a reference to.
+ const identifierPrefix = root.identifierPrefix;
+
let id;
if (getIsHydrating()) {
const treeId = getTreeId();
// Use a captial R prefix for server-generated ids.
- id = 'R:' + treeId;
+ id = identifierPrefix + 'R:' + treeId;
// Unless this is the first id at this level, append a number at the end
// that represents the position of this useId hook among all the useId
@@ -2052,7 +2060,7 @@ function mountId(): string {
} else {
// Use a lowercase r prefix for client-generated ids.
const globalClientId = globalClientIdCounter++;
- id = 'r:' + globalClientId.toString(32);
+ id = identifierPrefix + 'r:' + globalClientId.toString(32);
}
hook.memoizedState = id;
diff --git a/packages/react-reconciler/src/ReactFiberHooks.old.js b/packages/react-reconciler/src/ReactFiberHooks.old.js
index ff6a9f652fb4d..077073bbeef3c 100644
--- a/packages/react-reconciler/src/ReactFiberHooks.old.js
+++ b/packages/react-reconciler/src/ReactFiberHooks.old.js
@@ -2035,12 +2035,20 @@ export function getIsUpdatingOpaqueValueInRenderPhaseInDEV(): boolean | void {
function mountId(): string {
const hook = mountWorkInProgressHook();
+ const root = ((getWorkInProgressRoot(): any): FiberRoot);
+ // TODO: In Fizz, id generation is specific to each server config. Maybe we
+ // should do this in Fiber, too? Deferring this decision for now because
+ // there's no other place to store the prefix except for an internal field on
+ // the public createRoot object, which the fiber tree does not currently have
+ // a reference to.
+ const identifierPrefix = root.identifierPrefix;
+
let id;
if (getIsHydrating()) {
const treeId = getTreeId();
// Use a captial R prefix for server-generated ids.
- id = 'R:' + treeId;
+ id = identifierPrefix + 'R:' + treeId;
// Unless this is the first id at this level, append a number at the end
// that represents the position of this useId hook among all the useId
@@ -2052,7 +2060,7 @@ function mountId(): string {
} else {
// Use a lowercase r prefix for client-generated ids.
const globalClientId = globalClientIdCounter++;
- id = 'r:' + globalClientId.toString(32);
+ id = identifierPrefix + 'r:' + globalClientId.toString(32);
}
hook.memoizedState = id;
diff --git a/packages/react-reconciler/src/ReactFiberReconciler.new.js b/packages/react-reconciler/src/ReactFiberReconciler.new.js
index 6c42165a30347..1b8b9502de3ee 100644
--- a/packages/react-reconciler/src/ReactFiberReconciler.new.js
+++ b/packages/react-reconciler/src/ReactFiberReconciler.new.js
@@ -241,6 +241,7 @@ export function createContainer(
hydrationCallbacks: null | SuspenseHydrationCallbacks,
isStrictMode: boolean,
concurrentUpdatesByDefaultOverride: null | boolean,
+ identifierPrefix: string,
): OpaqueRoot {
return createFiberRoot(
containerInfo,
@@ -249,6 +250,7 @@ export function createContainer(
hydrationCallbacks,
isStrictMode,
concurrentUpdatesByDefaultOverride,
+ identifierPrefix,
);
}
diff --git a/packages/react-reconciler/src/ReactFiberReconciler.old.js b/packages/react-reconciler/src/ReactFiberReconciler.old.js
index 7693cc7fe4006..8649ff6989841 100644
--- a/packages/react-reconciler/src/ReactFiberReconciler.old.js
+++ b/packages/react-reconciler/src/ReactFiberReconciler.old.js
@@ -241,6 +241,7 @@ export function createContainer(
hydrationCallbacks: null | SuspenseHydrationCallbacks,
isStrictMode: boolean,
concurrentUpdatesByDefaultOverride: null | boolean,
+ identifierPrefix: string,
): OpaqueRoot {
return createFiberRoot(
containerInfo,
@@ -249,6 +250,7 @@ export function createContainer(
hydrationCallbacks,
isStrictMode,
concurrentUpdatesByDefaultOverride,
+ identifierPrefix,
);
}
diff --git a/packages/react-reconciler/src/ReactFiberRoot.new.js b/packages/react-reconciler/src/ReactFiberRoot.new.js
index 803adee1e22dd..9e9feb45d9b03 100644
--- a/packages/react-reconciler/src/ReactFiberRoot.new.js
+++ b/packages/react-reconciler/src/ReactFiberRoot.new.js
@@ -30,7 +30,7 @@ import {initializeUpdateQueue} from './ReactUpdateQueue.new';
import {LegacyRoot, ConcurrentRoot} from './ReactRootTags';
import {createCache, retainCache} from './ReactFiberCacheComponent.new';
-function FiberRootNode(containerInfo, tag, hydrate) {
+function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix) {
this.tag = tag;
this.containerInfo = containerInfo;
this.pendingChildren = null;
@@ -56,6 +56,8 @@ function FiberRootNode(containerInfo, tag, hydrate) {
this.entangledLanes = NoLanes;
this.entanglements = createLaneMap(NoLanes);
+ this.identifierPrefix = identifierPrefix;
+
if (enableCache) {
this.pooledCache = null;
this.pooledCacheLanes = NoLanes;
@@ -101,8 +103,14 @@ export function createFiberRoot(
hydrationCallbacks: null | SuspenseHydrationCallbacks,
isStrictMode: boolean,
concurrentUpdatesByDefaultOverride: null | boolean,
+ identifierPrefix: string,
): FiberRoot {
- const root: FiberRoot = (new FiberRootNode(containerInfo, tag, hydrate): any);
+ const root: FiberRoot = (new FiberRootNode(
+ containerInfo,
+ tag,
+ hydrate,
+ identifierPrefix,
+ ): any);
if (enableSuspenseCallback) {
root.hydrationCallbacks = hydrationCallbacks;
}
diff --git a/packages/react-reconciler/src/ReactFiberRoot.old.js b/packages/react-reconciler/src/ReactFiberRoot.old.js
index 504dac966ef22..d8d061297854f 100644
--- a/packages/react-reconciler/src/ReactFiberRoot.old.js
+++ b/packages/react-reconciler/src/ReactFiberRoot.old.js
@@ -30,7 +30,7 @@ import {initializeUpdateQueue} from './ReactUpdateQueue.old';
import {LegacyRoot, ConcurrentRoot} from './ReactRootTags';
import {createCache, retainCache} from './ReactFiberCacheComponent.old';
-function FiberRootNode(containerInfo, tag, hydrate) {
+function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix) {
this.tag = tag;
this.containerInfo = containerInfo;
this.pendingChildren = null;
@@ -56,6 +56,8 @@ function FiberRootNode(containerInfo, tag, hydrate) {
this.entangledLanes = NoLanes;
this.entanglements = createLaneMap(NoLanes);
+ this.identifierPrefix = identifierPrefix;
+
if (enableCache) {
this.pooledCache = null;
this.pooledCacheLanes = NoLanes;
@@ -101,8 +103,14 @@ export function createFiberRoot(
hydrationCallbacks: null | SuspenseHydrationCallbacks,
isStrictMode: boolean,
concurrentUpdatesByDefaultOverride: null | boolean,
+ identifierPrefix: string,
): FiberRoot {
- const root: FiberRoot = (new FiberRootNode(containerInfo, tag, hydrate): any);
+ const root: FiberRoot = (new FiberRootNode(
+ containerInfo,
+ tag,
+ hydrate,
+ identifierPrefix,
+ ): any);
if (enableSuspenseCallback) {
root.hydrationCallbacks = hydrationCallbacks;
}
diff --git a/packages/react-reconciler/src/ReactInternalTypes.js b/packages/react-reconciler/src/ReactInternalTypes.js
index db964103836da..13965720b7cd3 100644
--- a/packages/react-reconciler/src/ReactInternalTypes.js
+++ b/packages/react-reconciler/src/ReactInternalTypes.js
@@ -239,6 +239,13 @@ type BaseFiberRootProperties = {|
pooledCache: Cache | null,
pooledCacheLanes: Lanes,
+
+ // TODO: In Fizz, id generation is specific to each server config. Maybe we
+ // should do this in Fiber, too? Deferring this decision for now because
+ // there's no other place to store the prefix except for an internal field on
+ // the public createRoot object, which the fiber tree does not currently have
+ // a reference to.
+ identifierPrefix: string,
|};
// The following attributes are only used by DevTools and are only present in DEV builds.
diff --git a/packages/react-reconciler/src/__tests__/ReactFiberHostContext-test.internal.js b/packages/react-reconciler/src/__tests__/ReactFiberHostContext-test.internal.js
index ee4bd306481b0..4bf292df79f7a 100644
--- a/packages/react-reconciler/src/__tests__/ReactFiberHostContext-test.internal.js
+++ b/packages/react-reconciler/src/__tests__/ReactFiberHostContext-test.internal.js
@@ -74,6 +74,8 @@ describe('ReactFiberHostContext', () => {
ConcurrentRoot,
false,
null,
+ false,
+ '',
);
act(() => {
Renderer.updateContainer(
@@ -135,6 +137,8 @@ describe('ReactFiberHostContext', () => {
ConcurrentRoot,
false,
null,
+ false,
+ '',
);
act(() => {
Renderer.updateContainer(
diff --git a/packages/react-server/src/ReactFizzHooks.js b/packages/react-server/src/ReactFizzHooks.js
index 926a1969bb48a..5997f1b02b902 100644
--- a/packages/react-server/src/ReactFizzHooks.js
+++ b/packages/react-server/src/ReactFizzHooks.js
@@ -22,6 +22,8 @@ import type {Task} from './ReactFizzServer';
import {readContext as readContextImpl} from './ReactFizzNewContext';
import {getTreeId} from './ReactFizzTreeContext';
+import {makeId} from './ReactServerFormatConfig';
+
import {enableCache} from 'shared/ReactFeatureFlags';
import is from 'shared/objectIs';
@@ -512,18 +514,15 @@ function useId(): string {
const task: Task = (currentlyRenderingTask: any);
const treeId = getTreeId(task.treeContext);
- // Use a captial R prefix for server-generated ids.
- let id = 'R:' + treeId;
-
- // Unless this is the first id at this level, append a number at the end
- // that represents the position of this useId hook among all the useId
- // hooks for this fiber.
- const localId = localIdCounter++;
- if (localId > 0) {
- id += ':' + localId.toString(32);
+ const responseState = currentResponseState;
+ if (responseState === null) {
+ throw new Error(
+ 'Invalid hook call. Hooks can only be called inside of the body of a function component.',
+ );
}
- return id;
+ const localId = localIdCounter++;
+ return makeId(responseState, treeId, localId);
}
function unsupportedRefresh() {
diff --git a/packages/react-server/src/forks/ReactServerFormatConfig.custom.js b/packages/react-server/src/forks/ReactServerFormatConfig.custom.js
index f246ddab8b5bf..035490fb3f65a 100644
--- a/packages/react-server/src/forks/ReactServerFormatConfig.custom.js
+++ b/packages/react-server/src/forks/ReactServerFormatConfig.custom.js
@@ -35,6 +35,7 @@ export const getChildFormatContext = $$$hostConfig.getChildFormatContext;
export const UNINITIALIZED_SUSPENSE_BOUNDARY_ID =
$$$hostConfig.UNINITIALIZED_SUSPENSE_BOUNDARY_ID;
export const assignSuspenseBoundaryID = $$$hostConfig.assignSuspenseBoundaryID;
+export const makeId = $$$hostConfig.makeId;
export const pushTextInstance = $$$hostConfig.pushTextInstance;
export const pushStartInstance = $$$hostConfig.pushStartInstance;
export const pushEndInstance = $$$hostConfig.pushEndInstance;
diff --git a/packages/react-test-renderer/src/ReactTestRenderer.js b/packages/react-test-renderer/src/ReactTestRenderer.js
index 2e49968e85ded..de6e4beffec5f 100644
--- a/packages/react-test-renderer/src/ReactTestRenderer.js
+++ b/packages/react-test-renderer/src/ReactTestRenderer.js
@@ -471,6 +471,7 @@ function create(element: React$Element, options: TestRendererOptions) {
null,
isStrictMode,
concurrentUpdatesByDefault,
+ '',
);
if (root == null) {