Skip to content

Commit af94b4f

Browse files
authored
feat: added new react useid hook and tests (#14044)
1 parent c3ea7c8 commit af94b4f

7 files changed

Lines changed: 74 additions & 31 deletions

File tree

packages/react/src/components/Accordion/__tests__/__snapshots__/Accordion-test.js.snap

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ exports[`Accordion should render 1`] = `
99
class="cds--accordion__item child"
1010
>
1111
<button
12-
aria-controls="accordion-item-1"
12+
aria-controls="accordion-item-:r0:"
1313
aria-expanded="false"
1414
class="cds--accordion__heading"
1515
type="button"
@@ -38,7 +38,7 @@ exports[`Accordion should render 1`] = `
3838
</button>
3939
<div
4040
class="cds--accordion__content"
41-
id="accordion-item-1"
41+
id="accordion-item-:r0:"
4242
>
4343
Panel A
4444
</div>
@@ -47,7 +47,7 @@ exports[`Accordion should render 1`] = `
4747
class="cds--accordion__item child"
4848
>
4949
<button
50-
aria-controls="accordion-item-2"
50+
aria-controls="accordion-item-:r1:"
5151
aria-expanded="false"
5252
class="cds--accordion__heading"
5353
type="button"
@@ -76,7 +76,7 @@ exports[`Accordion should render 1`] = `
7676
</button>
7777
<div
7878
class="cds--accordion__content"
79-
id="accordion-item-2"
79+
id="accordion-item-:r1:"
8080
>
8181
Panel B
8282
</div>
@@ -85,7 +85,7 @@ exports[`Accordion should render 1`] = `
8585
class="cds--accordion__item child"
8686
>
8787
<button
88-
aria-controls="accordion-item-3"
88+
aria-controls="accordion-item-:r2:"
8989
aria-expanded="false"
9090
class="cds--accordion__heading"
9191
type="button"
@@ -114,7 +114,7 @@ exports[`Accordion should render 1`] = `
114114
</button>
115115
<div
116116
class="cds--accordion__content"
117-
id="accordion-item-3"
117+
id="accordion-item-:r2:"
118118
>
119119
Panel C
120120
</div>

packages/react/src/components/Accordion/__tests__/__snapshots__/AccordionItem-test.js.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ exports[`AccordionItem renders as expected - Component API should render and mat
66
class="cds--accordion__item extra-class"
77
>
88
<button
9-
aria-controls="accordion-item-2"
9+
aria-controls="accordion-item-:r1:"
1010
aria-expanded="false"
1111
class="cds--accordion__heading"
1212
type="button"
@@ -35,7 +35,7 @@ exports[`AccordionItem renders as expected - Component API should render and mat
3535
</button>
3636
<div
3737
class="cds--accordion__content"
38-
id="accordion-item-2"
38+
id="accordion-item-:r1:"
3939
>
4040
Lorem ipsum.
4141
</div>

packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,20 @@ exports[`DataTable behaves as expected selection -- radio buttons should not hav
1010
>
1111
<h4
1212
class="cds--data-table-header__title"
13-
id="tc-149-title"
13+
id="tc-:r4k:-title"
1414
>
1515
DataTable with selection
1616
</h4>
1717
<p
1818
class="cds--data-table-header__description"
19-
id="tc-149-description"
19+
id="tc-:r4k:-description"
2020
/>
2121
</div>
2222
<div
2323
class="cds--data-table-content"
2424
>
2525
<table
26-
aria-labelledby="tc-149-title"
26+
aria-labelledby="tc-:r4k:-title"
2727
class="cds--data-table cds--data-table--lg"
2828
>
2929
<thead>
@@ -179,20 +179,20 @@ exports[`DataTable behaves as expected selection -- radio buttons should render
179179
>
180180
<h4
181181
class="cds--data-table-header__title"
182-
id="tc-143-title"
182+
id="tc-:r4e:-title"
183183
>
184184
DataTable with selection
185185
</h4>
186186
<p
187187
class="cds--data-table-header__description"
188-
id="tc-143-description"
188+
id="tc-:r4e:-description"
189189
/>
190190
</div>
191191
<div
192192
class="cds--data-table-content"
193193
>
194194
<table
195-
aria-labelledby="tc-143-title"
195+
aria-labelledby="tc-:r4e:-title"
196196
class="cds--data-table cds--data-table--lg"
197197
>
198198
<thead>
@@ -348,13 +348,13 @@ exports[`DataTable behaves as expected selection should render and match snapsho
348348
>
349349
<h4
350350
class="cds--data-table-header__title"
351-
id="tc-67-title"
351+
id="tc-:r22:-title"
352352
>
353353
DataTable with selection
354354
</h4>
355355
<p
356356
class="cds--data-table-header__description"
357-
id="tc-67-description"
357+
id="tc-:r22:-description"
358358
/>
359359
</div>
360360
<section
@@ -552,7 +552,7 @@ exports[`DataTable behaves as expected selection should render and match snapsho
552552
<button
553553
aria-expanded="false"
554554
aria-haspopup="true"
555-
aria-labelledby="tooltip-73"
555+
aria-labelledby="tooltip-:r28:"
556556
class="cds--btn--icon-only cds--toolbar-action cds--overflow-menu cds--overflow-menu cds--overflow-menu--md cds--btn cds--btn--md cds--layout--size-md cds--btn--primary"
557557
title="Settings"
558558
type="button"
@@ -581,7 +581,7 @@ exports[`DataTable behaves as expected selection should render and match snapsho
581581
<span
582582
aria-hidden="true"
583583
class="cds--popover"
584-
id="tooltip-73"
584+
id="tooltip-:r28:"
585585
role="tooltip"
586586
>
587587
<span
@@ -607,7 +607,7 @@ exports[`DataTable behaves as expected selection should render and match snapsho
607607
class="cds--data-table-content"
608608
>
609609
<table
610-
aria-labelledby="tc-67-title"
610+
aria-labelledby="tc-:r22:-title"
611611
class="cds--data-table cds--data-table--lg"
612612
>
613613
<thead>
@@ -754,13 +754,13 @@ exports[`DataTable renders as expected - Component API should render and match s
754754
>
755755
<h4
756756
class="cds--data-table-header__title"
757-
id="tc-12-title"
757+
id="tc-:rb:-title"
758758
>
759759
DataTable with toolbar
760760
</h4>
761761
<p
762762
class="cds--data-table-header__description"
763-
id="tc-12-description"
763+
id="tc-:rb:-description"
764764
/>
765765
</div>
766766
<section
@@ -958,7 +958,7 @@ exports[`DataTable renders as expected - Component API should render and match s
958958
<button
959959
aria-expanded="false"
960960
aria-haspopup="true"
961-
aria-labelledby="tooltip-18"
961+
aria-labelledby="tooltip-:rh:"
962962
class="cds--btn--icon-only cds--toolbar-action cds--overflow-menu cds--overflow-menu cds--overflow-menu--md cds--btn cds--btn--md cds--layout--size-md cds--btn--primary"
963963
title="Settings"
964964
type="button"
@@ -987,7 +987,7 @@ exports[`DataTable renders as expected - Component API should render and match s
987987
<span
988988
aria-hidden="true"
989989
class="cds--popover"
990-
id="tooltip-18"
990+
id="tooltip-:rh:"
991991
role="tooltip"
992992
>
993993
<span
@@ -1013,7 +1013,7 @@ exports[`DataTable renders as expected - Component API should render and match s
10131013
class="cds--data-table-content"
10141014
>
10151015
<table
1016-
aria-labelledby="tc-12-title"
1016+
aria-labelledby="tc-:rb:-title"
10171017
class="cds--data-table cds--data-table--lg"
10181018
>
10191019
<thead>

packages/react/src/components/DataTable/__tests__/__snapshots__/TableToolbarMenu-test.js.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ exports[`TableToolbarMenu renders as expected - Component API should render 1`]
1414
<button
1515
aria-expanded="false"
1616
aria-haspopup="true"
17-
aria-labelledby="tooltip-2"
17+
aria-labelledby="tooltip-:r0:"
1818
class="cds--btn--icon-only custom-class cds--toolbar-action cds--overflow-menu cds--overflow-menu cds--overflow-menu--md cds--btn cds--btn--md cds--layout--size-md cds--btn--primary"
1919
title="Add"
2020
type="button"
@@ -40,7 +40,7 @@ exports[`TableToolbarMenu renders as expected - Component API should render 1`]
4040
<span
4141
aria-hidden="true"
4242
class="cds--popover"
43-
id="tooltip-2"
43+
id="tooltip-:r0:"
4444
role="tooltip"
4545
>
4646
<span

packages/react/src/internal/__tests__/useId-test.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import { render, screen } from '@testing-library/react';
99
import React from 'react';
10-
import { useId } from '../useId';
10+
import { useId, useFallbackId } from '../useId';
1111

1212
describe('useId', () => {
1313
it('should generate a unique id that is stable across renders', () => {
@@ -17,6 +17,26 @@ describe('useId', () => {
1717
}
1818

1919
render(<Test />);
20-
expect(screen.getByText('test')).toHaveAttribute('id', 'test-1');
20+
expect(screen.getByText('test')).toHaveAttribute('id', 'test-:r0:');
21+
});
22+
23+
it('should generate a unique id when using the useFallbackId empty', () => {
24+
function Test() {
25+
const id = useFallbackId();
26+
return <span id={id}>test</span>;
27+
}
28+
29+
render(<Test />);
30+
expect(screen.getByText('test')).toHaveAttribute('id', 'id-:r1:');
31+
});
32+
33+
it('should recieved a unique id by passing a string on params when using useFallbackId', () => {
34+
function Test() {
35+
const id = useFallbackId('idRecieved');
36+
return <span id={id}>test</span>;
37+
}
38+
39+
render(<Test />);
40+
expect(screen.getByText('test')).toHaveAttribute('id', 'idRecieved');
2141
});
2242
});

packages/react/src/internal/__tests__/useId.server-test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ import { renderToString } from 'react-dom/server';
1212
import { useId } from '../useId';
1313

1414
describe('useId SSR', () => {
15-
it('should not generate an id on the server', () => {
15+
it('should generate an id on the server', () => {
1616
function Test() {
1717
const id = useId('test');
1818
return <span id={id}>test</span>;
1919
}
2020
const view = renderToString(<Test />);
21-
expect(view.indexOf('id="')).toBe(-1);
21+
expect(view.indexOf('id="')).toBe(6);
2222
});
2323
});

packages/react/src/internal/useId.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,18 @@
2222
// This ensures that we won't encounter a mismatch in ids between server and
2323
// client, at the cost of runtime patching of the id value in
2424
// `useLayoutEffect`
25+
//
26+
// React 18 introduced a new hook called `useId` that takes care of hydration
27+
// mismatches. Now we are checking if the user is running React 18 to apply
28+
// the new hook and call the `nativeReactUseid` function, but if the user is
29+
// running a version older than React 18 we will keep using our old hook.
2530

26-
import { useEffect, useLayoutEffect, useState } from 'react';
31+
import {
32+
useEffect,
33+
useLayoutEffect,
34+
useState,
35+
useId as reactUseId,
36+
} from 'react';
2737
import setupGetInstanceId from '../tools/setupGetInstanceId';
2838
import { canUseDOM } from './environment';
2939
import { useIdPrefix } from './useIdPrefix';
@@ -60,6 +70,19 @@ export function useId(prefix = 'id') {
6070
}
6171
}, []);
6272

73+
if (reactUseId) {
74+
const id = nativeReactUseId(_prefix, prefix);
75+
return id;
76+
}
77+
78+
return id;
79+
}
80+
81+
function nativeReactUseId(_prefix, prefix) {
82+
const getId = reactUseId();
83+
84+
const id = `${_prefix ? `${_prefix}-` : ``}${prefix}-${getId}`;
85+
6386
return id;
6487
}
6588

0 commit comments

Comments
 (0)