0162c57d88
* bump dev dependencies to React 18 * setup Jest to include `IS_REACT_ACT_ENVIRONMENT` * prefer `useId` from React 18 if it exists In React 16 & 17, where `useId` doesn't exist, we will fallback to our implementation we have been using up until now. The `useId` exposed by React 18, ensures stable references even in SSR environments. * update expected events React 18 now uses the proper events: - `blur` -> `focusout` - `focus` -> `focusin` * ensure to wait a bit longer This is a bit unfortunate, but since React 18 now does an extra unmount/remount in `StrictMode` to ensure that your code is ConcurrentMode ready, it takes a bit longer to settle what the DOM sees. That said, this is a temporary "hack". We are going to experiment with using tools like Puppeteer/Playwright to run our tests in an actual browser instead to eliminate all the weird details that we have to keep in mind. * prefer `.focus()` over `fireEvent.focus(el)` * abstract `microTask` polyfill code * prefer our `focus(el)` function over `el.focus()` Internally we would still use `el.focus()`, but this allows us to have more control over that `focus` function. * add React 18 to the React Playground * improve hooks for React 18 - Improving the cleanup of useEffect hooks - useIsoMorphicEffect instead of normal useEffect, so that we can use useLayoutEffect to be a bit quicker. * improve disposables - This allows us to add event listeners on a node, and get automatic cleanup once `dispose` gets called. - We also return all the `d.add` calls, so that we can cleanup specific parts only instead of everything or nothing. * reimplement the Transition component to be React 18 ready * wait an additional frame for everything to settle * update playground examples * suppressConsoleLogs for RadioGroup components * update changelog * keep the `to` classes for a smoother transition In the next transition we will remove _all_ classes provided and re-add the once we need. --- Some extra special thanks: - Thanks @silvenon for your initial work on the `transition` events in #926 - Thanks @thecrypticace for doing late-night debugging sessions Co-authored-by: =?UTF-8?q?Matija=20Marohni=C4=87?= <matija.marohnic@gmail.com> Co-authored-by: Jordan Pittman <jordan@cryptica.me>
30 lines
925 B
TypeScript
30 lines
925 B
TypeScript
import React from 'react'
|
|
import { useIsoMorphicEffect } from './use-iso-morphic-effect'
|
|
import { useServerHandoffComplete } from './use-server-handoff-complete'
|
|
|
|
// We used a "simple" approach first which worked for SSR and rehydration on the client. However we
|
|
// didn't take care of the Suspense case. To fix this we used the approach the @reach-ui/auto-id
|
|
// uses.
|
|
//
|
|
// Credits: https://github.com/reach/reach-ui/blob/develop/packages/auto-id/src/index.tsx
|
|
|
|
let id = 0
|
|
function generateId() {
|
|
return ++id
|
|
}
|
|
|
|
export let useId =
|
|
// Prefer React's `useId` if it's available.
|
|
// @ts-expect-error - `useId` doesn't exist in React < 18.
|
|
React.useId ??
|
|
function useId() {
|
|
let ready = useServerHandoffComplete()
|
|
let [id, setId] = React.useState(ready ? generateId : null)
|
|
|
|
useIsoMorphicEffect(() => {
|
|
if (id === null) setId(generateId())
|
|
}, [id])
|
|
|
|
return id != null ? '' + id : undefined
|
|
}
|