Skip to content

Commit

Permalink
perf: useId logic
Browse files Browse the repository at this point in the history
  • Loading branch information
zombieJ committed Oct 12, 2023
1 parent 9d5cb89 commit 5e4679f
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 58 deletions.
59 changes: 37 additions & 22 deletions src/hooks/useId.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,32 +18,47 @@ export function resetUuid() {
}
}

export default function useId(id?: string) {
// Inner id for accessibility usage. Only work in client side
const [innerId, setInnerId] = React.useState<string>('ssr-id');
const useOriginId = getUseId();

const useOriginId = getUseId();
const reactNativeId = useOriginId?.();
export default useOriginId
? // Use React `useId`
function useId(id?: string) {
const reactId = useOriginId();

React.useEffect(() => {
if (!useOriginId) {
const nextId = uuid;
uuid += 1;
// Developer passed id is single source of truth
if (id) {
return id;
}

setInnerId(`rc_unique_${nextId}`);
// Test env always return mock id
if (process.env.NODE_ENV === 'test') {
return 'test-id';
}

return reactId;
}
}, []);
: // Use compatible of `useId`
function useCompatId(id?: string) {
// Inner id for accessibility usage. Only work in client side
const [innerId, setInnerId] = React.useState<string>('ssr-id');

// Developer passed id is single source of truth
if (id) {
return id;
}
React.useEffect(() => {
const nextId = uuid;
uuid += 1;

// Test env always return mock id
if (process.env.NODE_ENV === 'test') {
return 'test-id';
}
setInnerId(`rc_unique_${nextId}`);
}, []);

// Return react native id or inner id
return reactNativeId || innerId;
}
// Developer passed id is single source of truth
if (id) {
return id;
}

// Test env always return mock id
if (process.env.NODE_ENV === 'test') {
return 'test-id';
}

// Return react native id or inner id
return innerId;
};
63 changes: 63 additions & 0 deletions tests/hooks-17.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { render } from '@testing-library/react';
import * as React from 'react';
import { renderToString } from 'react-dom/server';
import useId, { resetUuid } from '../src/hooks/useId';

jest.mock('react', () => {
const react = jest.requireActual('react');

const clone = { ...react };

Object.defineProperty(clone, 'useId', {
get: () => null,
});

return clone;
});

describe('hooks-17', () => {
describe('useId', () => {
const Demo = ({ id } = {}) => {
const mergedId = useId(id);
return <div id={mergedId} className="target" />;
};

function matchId(container, id) {
const ele = container.querySelector('.target');
return expect(ele.id).toEqual(id);
}

it('fallback of React 17 or lower', () => {
const errorSpy = jest.spyOn(console, 'error');
const originEnv = process.env.NODE_ENV;
process.env.NODE_ENV = 'development';

// SSR
const content = renderToString(
<React.StrictMode>
<Demo />
</React.StrictMode>,
);
expect(content).toContain('ssr-id');

// Hydrate
resetUuid();
const holder = document.createElement('div');
holder.innerHTML = content;
const { container } = render(
<React.StrictMode>
<Demo />
</React.StrictMode>,
{
hydrate: true,
container: holder,
},
);

matchId(container, 'rc_unique_1');

errorSpy.mockRestore();
process.env.NODE_ENV = originEnv;
});
});
});
37 changes: 1 addition & 36 deletions tests/hooks.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { fireEvent, render } from '@testing-library/react';
import * as React from 'react';
import { renderToString } from 'react-dom/server';
import useId, { resetUuid } from '../src/hooks/useId';
import useId from '../src/hooks/useId';
import useLayoutEffect from '../src/hooks/useLayoutEffect';
import useMemo from '../src/hooks/useMemo';
import useMergedState from '../src/hooks/useMergedState';
Expand Down Expand Up @@ -487,41 +487,6 @@ describe('hooks', () => {
errorSpy.mockRestore();
process.env.NODE_ENV = originEnv;
});

it('fallback of React 17 or lower', () => {
const errorSpy = jest.spyOn(console, 'error');
const originEnv = process.env.NODE_ENV;
process.env.NODE_ENV = 'development';
global.disableUseId = true;

// SSR
const content = renderToString(
<React.StrictMode>
<Demo />
</React.StrictMode>,
);
expect(content).toContain('ssr-id');

// Hydrate
resetUuid();
const holder = document.createElement('div');
holder.innerHTML = content;
const { container } = render(
<React.StrictMode>
<Demo />
</React.StrictMode>,
{
hydrate: true,
container: holder,
},
);

matchId(container, 'rc_unique_1');

errorSpy.mockRestore();
process.env.NODE_ENV = originEnv;
global.disableUseId = false;
});
});

describe('useMobile', () => {
Expand Down

0 comments on commit 5e4679f

Please sign in to comment.