UNPKG

vcc-ui

Version:

A React library for building user interfaces at Volvo Cars

58 lines (56 loc) 1.92 kB
import { useEffect, useLayoutEffect, useState } from 'react'; const useUniversalLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect; let serverHandoffComplete = false; let id = 0; function genId(prefix) { id++; return `${prefix}-${id}`; } /** * useId * * Autogenerate IDs to facilitate WAI-ARIA and server rendering. * * Note: The returned ID will initially be `null` and will update after a * component mounts. Users may need to supply their own ID if they need * consistent values for SSR. */ export function useId(prefix, idFromProps) { /* * If this instance isn't part of the initial render, we don't have to do the * double render/patch-up dance. We can just generate the ID and return it. */ const initialId = idFromProps || (serverHandoffComplete ? genId(prefix) : null); const [id, setId] = useState(initialId); useUniversalLayoutEffect(() => { if (id === null) { /* * Patch the ID after render. We do this in `useLayoutEffect` to avoid any * rendering flicker, though it'll make the first render slower (unlikely * to matter, but you're welcome to measure your app and let us know if * it's a problem). */ setId(genId(prefix)); } }, []); useEffect(() => { if (serverHandoffComplete === false) { /* * Flag all future uses of `useId` to skip the update dance. This is in * `useEffect` because it goes after `useLayoutEffect`, ensuring we don't * accidentally bail out of the patch-up dance prematurely. */ serverHandoffComplete = true; } }, []); return id != null ? String(id) : undefined; } export function makeId(rootId, part) { return rootId != null ? `${rootId}--${part}` : undefined; } /** * Make list of ids for aria attributes. */ export function makeIdList(ids) { return ids.filter(id => typeof id === 'string').join(' ').trim(); }