Skip to content

Commit 2a647a7

Browse files
Ensure refs are forwarded when freezing data (#3390)
We were wrapping rendered children in `<Frozen>` in a combobox however the refs weren't being forwarded through the internal `<Frozen>` component resulting in issues when rendering `<ComboboxOptions>` as a `Fragment`. After this PR the following code no longer warns about function components not accepting refs. ```tsx import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react' import React from 'react' export default function Example() { return ( <div className="p-4"> <Combobox> <ComboboxInput className="rounded border border-neutral-400 p-2" /> <ComboboxOptions as={React.Fragment}> <div className="bg-orange-500 p-4"> <ComboboxOption value="a">A</ComboboxOption> </div> </ComboboxOptions> </Combobox> </div> ) } ``` Fixes #3384 --------- Co-authored-by: Robin Malfait <[email protected]>
1 parent da2fa94 commit 2a647a7

File tree

2 files changed

+13
-2
lines changed

2 files changed

+13
-2
lines changed

packages/@headlessui-react/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1616
- Allow home/end key default behavior inside `ComboboxInput` when `Combobox` is closed ([#3798](https://github.com/tailwindlabs/headlessui/pull/3798))
1717
- Ensure interacting with a `Dialog` on iOS works after interacting with a disallowed area ([#3801](https://github.com/tailwindlabs/headlessui/pull/3801))
1818
- Freeze Listbox values as soon as possible when closing ([#3802](https://github.com/tailwindlabs/headlessui/pull/3802))
19+
- Ensure refs are forwarded when freezing data ([#3390](https://github.com/tailwindlabs/headlessui/pull/3390))
1920

2021
## [2.2.8] - 2025-09-12
2122

packages/@headlessui-react/src/internal/frozen.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
1-
import React, { useState } from 'react'
1+
import React, { cloneElement, isValidElement, useState } from 'react'
22

3-
export function Frozen({ children, freeze }: { children: React.ReactNode; freeze: boolean }) {
3+
function FrozenFn(
4+
{ children, freeze }: { children: React.ReactNode; freeze: boolean },
5+
ref: React.ForwardedRef<HTMLElement>
6+
) {
47
let contents = useFrozenData(freeze, children)
8+
9+
if (isValidElement(contents)) {
10+
return cloneElement(contents as React.ReactElement, { ref })
11+
}
12+
513
return <>{contents}</>
614
}
715

16+
export const Frozen = React.forwardRef(FrozenFn)
17+
818
export function useFrozenData<T>(freeze: boolean, data: T) {
919
let [frozenValue, setFrozenValue] = useState(data)
1020

0 commit comments

Comments
 (0)