Skip to content

Instantly share code, notes, and snippets.

@yarastqt
Created September 14, 2020 11:54
Show Gist options
  • Save yarastqt/a35261d77d723d14f6d1945dd8130b94 to your computer and use it in GitHub Desktop.
Save yarastqt/a35261d77d723d14f6d1945dd8130b94 to your computer and use it in GitHub Desktop.
import {
EffectCallback,
DependencyList,
useLayoutEffect,
useState,
useEffect,
useMemo,
} from 'react'
// lib/canUseDOM
const canUseDOM = (): boolean => {
return (
typeof window !== 'undefined' &&
typeof window.document !== 'undefined' &&
typeof window.document.createElement !== 'undefined'
)
}
// lib/useIsomorphicLayoutEffect
function useIsomorphicLayoutEffect(fn: EffectCallback, deps: DependencyList): void {
return canUseDOM() ? useLayoutEffect(fn, deps) : useEffect(fn, deps)
}
let isClientEnv = false
let id = 0
function generateId(prefix: string) {
return `${prefix}${++id}`
}
export function useUniqId(prefix: string = ''): string | undefined {
const idRef = useMemo(() => (isClientEnv ? generateId(prefix) : undefined), [])
const [id, setId] = useState(idRef)
useIsomorphicLayoutEffect(() => {
if (id === undefined) {
setId(generateId(prefix))
}
}, [])
useEffect(() => {
if (!isClientEnv) {
isClientEnv = true
}
}, [])
return id
}
@yarastqt
Copy link
Author

usage

function MyComponent() {
  const id = useUniqId()
  // From server we get undefined, after mount and update we get generated id.
  return <div id={id} />
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment