diff --git a/packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js b/packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js index 5b36039ecc5dc..f5003e96bdf6c 100644 --- a/packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js +++ b/packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js @@ -614,7 +614,7 @@ describe('ReactHooksInspectionIntegration', () => { expect(tree[0].id).toEqual(0); expect(tree[0].isStateEditable).toEqual(false); expect(tree[0].name).toEqual('Id'); - expect(String(tree[0].value).startsWith('r:')).toBe(true); + expect(String(tree[0].value).startsWith(':r')).toBe(true); expect(tree[1]).toEqual({ id: 1, diff --git a/packages/react-dom/src/__tests__/ReactDOMUseId-test.js b/packages/react-dom/src/__tests__/ReactDOMUseId-test.js index 036c138d5e97a..41c4ddcbcc489 100644 --- a/packages/react-dom/src/__tests__/ReactDOMUseId-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMUseId-test.js @@ -93,7 +93,11 @@ describe('useId', () => { } function normalizeTreeIdForTesting(id) { - const [serverClientPrefix, base32, hookIndex] = id.split(':'); + const result = id.match(/:(R|r)(.*):(([0-9]*):)?/); + if (result === undefined) { + throw new Error('Invalid id format'); + } + const [, serverClientPrefix, base32, hookIndex] = result; if (serverClientPrefix.endsWith('r')) { // Client ids aren't stable. For testing purposes, strip out the counter. return ( @@ -278,7 +282,7 @@ describe('useId', () => { // 'R:' prefix, and the first character after that, which may not correspond // to a complete set of 5 bits. // - // Example: R:clalalalalalalala... + // Example: :Rclalalalalalalala...: // // We can use this pattern to test large ids that exceed the bitwise // safe range (32 bits). The algorithm should theoretically support ids @@ -313,8 +317,8 @@ describe('useId', () => { // Confirm that every id matches the expected pattern for (let i = 0; i < divs.length; i++) { - // Example: R:clalalalalalalala... - expect(divs[i].id).toMatch(/^R:.(((al)*a?)((la)*l?))*$/); + // Example: :Rclalalalalalalala...: + expect(divs[i].id).toMatch(/^:R.(((al)*a?)((la)*l?))*:$/); } }); @@ -338,7 +342,7 @@ describe('useId', () => {
- R:0, R:0:1, R:0:2 + :R0:, :R0:1:, :R0:2:
`); @@ -364,7 +368,7 @@ describe('useId', () => {
- R:0 + :R0:
`); @@ -603,10 +607,10 @@ describe('useId', () => { id="container" >
- custom-prefix-R:1 + :custom-prefix-R1:
- custom-prefix-R:2 + :custom-prefix-R2:
`); @@ -620,13 +624,13 @@ describe('useId', () => { id="container" >
- custom-prefix-R:1 + :custom-prefix-R1:
- custom-prefix-R:2 + :custom-prefix-R2:
- custom-prefix-r:0 + :custom-prefix-r0:
`); diff --git a/packages/react-dom/src/server/ReactDOMServerFormatConfig.js b/packages/react-dom/src/server/ReactDOMServerFormatConfig.js index 20887c226015a..f623556bb62de 100644 --- a/packages/react-dom/src/server/ReactDOMServerFormatConfig.js +++ b/packages/react-dom/src/server/ReactDOMServerFormatConfig.js @@ -130,7 +130,7 @@ export function createResponseState( placeholderPrefix: stringToPrecomputedChunk(idPrefix + 'P:'), segmentPrefix: stringToPrecomputedChunk(idPrefix + 'S:'), boundaryPrefix: idPrefix + 'B:', - idPrefix: idPrefix + 'R:', + idPrefix: idPrefix, nextSuspenseID: 0, sentCompleteSegmentFunction: false, sentCompleteBoundaryFunction: false, @@ -242,13 +242,13 @@ export function makeId( ): string { const idPrefix = responseState.idPrefix; - let id = idPrefix + treeId; + let id = ':' + idPrefix + '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. if (localId > 0) { - id += ':' + localId.toString(32); + id += localId.toString(32) + ':'; } return id; diff --git a/packages/react-reconciler/src/ReactFiberHooks.new.js b/packages/react-reconciler/src/ReactFiberHooks.new.js index 3f64a7d8f9178..5c4b9357f909e 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.new.js +++ b/packages/react-reconciler/src/ReactFiberHooks.new.js @@ -2072,19 +2072,19 @@ function mountId(): string { const treeId = getTreeId(); // Use a captial R prefix for server-generated ids. - id = identifierPrefix + '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 // hooks for this fiber. const localId = localIdCounter++; if (localId > 0) { - id += ':' + localId.toString(32); + id += localId.toString(32) + ':'; } } else { // Use a lowercase r prefix for client-generated ids. const globalClientId = globalClientIdCounter++; - id = identifierPrefix + '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 d55cac9b26c74..f0fcef733d581 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.old.js +++ b/packages/react-reconciler/src/ReactFiberHooks.old.js @@ -2072,19 +2072,19 @@ function mountId(): string { const treeId = getTreeId(); // Use a captial R prefix for server-generated ids. - id = identifierPrefix + '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 // hooks for this fiber. const localId = localIdCounter++; if (localId > 0) { - id += ':' + localId.toString(32); + id += localId.toString(32) + ':'; } } else { // Use a lowercase r prefix for client-generated ids. const globalClientId = globalClientIdCounter++; - id = identifierPrefix + 'r:' + globalClientId.toString(32); + id = ':' + identifierPrefix + 'r' + globalClientId.toString(32) + ':'; } hook.memoizedState = id;