From 8814b0eecd11b09f9971e1845569ba3aa2d5056f Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Fri, 25 Oct 2024 15:50:58 +0200 Subject: [PATCH] Add React 19 support (#3543) This PR fixes an issue where `@headlessui/react` was not compatible with React 19. We made sure that accessing `ref`s is safe and works in React 18 and React 19. We also made sure to include React 19 as a valid version in the peer dependencies. For now, we also allowed the RC versions of React and React DOM. --- packages/@headlessui-react/CHANGELOG.md | 4 +++- packages/@headlessui-react/package.json | 4 ++-- packages/@headlessui-react/src/utils/render.ts | 9 +++++++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/@headlessui-react/CHANGELOG.md b/packages/@headlessui-react/CHANGELOG.md index d4c17470a..deeb12392 100644 --- a/packages/@headlessui-react/CHANGELOG.md +++ b/packages/@headlessui-react/CHANGELOG.md @@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -- Nothing yet! +### Added + +- Add React 19 support ([#3543](https://github.com/tailwindlabs/headlessui/pull/3543)) ## [2.1.10] - 2024-10-10 diff --git a/packages/@headlessui-react/package.json b/packages/@headlessui-react/package.json index dd94458f4..c5e42e0c3 100644 --- a/packages/@headlessui-react/package.json +++ b/packages/@headlessui-react/package.json @@ -42,8 +42,8 @@ "clean": "rimraf ./dist" }, "peerDependencies": { - "react": "^18", - "react-dom": "^18" + "react": "^18 || ^19 || ^19.0.0-rc", + "react-dom": "^18 || ^19 || ^19.0.0-rc" }, "devDependencies": { "@testing-library/react": "^15.0.7", diff --git a/packages/@headlessui-react/src/utils/render.ts b/packages/@headlessui-react/src/utils/render.ts index ae9a6b65b..36018cefe 100644 --- a/packages/@headlessui-react/src/utils/render.ts +++ b/packages/@headlessui-react/src/utils/render.ts @@ -1,4 +1,4 @@ -import { +import React, { Fragment, cloneElement, createElement, @@ -257,7 +257,7 @@ function _render( mergedProps, dataAttributes, refRelatedProps, - { ref: mergeRefs((resolvedChildren as any).ref, refRelatedProps.ref) }, + { ref: mergeRefs(getElementRef(resolvedChildren), refRelatedProps.ref) }, classNameProps ) ) @@ -460,3 +460,8 @@ function omit>(object: T, keysToOmit: string[] = []) } return clone } + +function getElementRef(element: React.ReactElement) { + // @ts-expect-error + return React.version.split('.')[0] >= '19' ? element.props.ref : element.ref +}