Skip to content

Commit 5fb738f

Browse files
authored
Fix flushSync warning for Combobox component with immediate prop enabled (#3366)
* wrap flushSync call in microTask This will make sure that React is able to flush this correctly by delaying the call using a microTask. * update changelog * reformat comments Now that it's nested, let's adjust the width of the comments
1 parent 91e9597 commit 5fb738f

File tree

2 files changed

+32
-6
lines changed

2 files changed

+32
-6
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
- Fix `transition` and `focus` prop combination for `PopoverPanel` component ([#3361](https://github.com/tailwindlabs/headlessui/pull/3361))
1717
- Fix outside click in nested portalled `Popover` components ([#3362](https://github.com/tailwindlabs/headlessui/pull/3362))
1818
- Fix restoring focus to correct element when closing `Dialog` component ([#3365](https://github.com/tailwindlabs/headlessui/pull/3365))
19+
- Fix `flushSync` warning for `Combobox` component with `immediate` prop enabled ([#3366](https://github.com/tailwindlabs/headlessui/pull/3366))
1920

2021
## [2.1.1] - 2024-06-26
2122

packages/@headlessui-react/src/components/combobox/combobox.tsx

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,12 +1321,37 @@ function InputFn<
13211321
if (!data.immediate) return
13221322
if (data.comboboxState === ComboboxState.Open) return
13231323

1324-
flushSync(() => actions.openCombobox())
1325-
1326-
// We need to make sure that tabbing through a form doesn't result in incorrectly setting the
1327-
// value of the combobox. We will set the activation trigger to `Focus`, and we will ignore
1328-
// selecting the active option when the user tabs away.
1329-
actions.setActivationTrigger(ActivationTrigger.Focus)
1324+
// In a scenario where you have this setup:
1325+
//
1326+
// ```ts
1327+
// {condition && (
1328+
// <Combobox immediate>
1329+
// <ComboboxInput autoFocus />
1330+
// </Combobox>
1331+
// )}
1332+
// ```
1333+
//
1334+
// Then we will trigger the `openCombobox` in a `flushSync`, but we are
1335+
// already in the middle of rendering. This will result in the following
1336+
// warning:
1337+
//
1338+
// ```
1339+
// Warning: flushSync was called from inside a lifecycle method. React
1340+
// cannot flush when React is already rendering. Consider moving this call
1341+
// to a scheduler task or micro task.
1342+
// ```
1343+
//
1344+
// Which is why we wrap this in a `microTask` to make sure we are not in the
1345+
// middle of rendering.
1346+
d.microTask(() => {
1347+
flushSync(() => actions.openCombobox())
1348+
1349+
// We need to make sure that tabbing through a form doesn't result in
1350+
// incorrectly setting the value of the combobox. We will set the
1351+
// activation trigger to `Focus`, and we will ignore selecting the active
1352+
// option when the user tabs away.
1353+
actions.setActivationTrigger(ActivationTrigger.Focus)
1354+
})
13301355
})
13311356

13321357
let labelledBy = useLabelledBy()

0 commit comments

Comments
 (0)