Skip to content

Commit

Permalink
Fix flushSync warning for Combobox component with immediate pro…
Browse files Browse the repository at this point in the history
…p 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
  • Loading branch information
RobinMalfait committed Jul 5, 2024
1 parent 91e9597 commit 5fb738f
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 6 deletions.
1 change: 1 addition & 0 deletions packages/@headlessui-react/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix `transition` and `focus` prop combination for `PopoverPanel` component ([#3361](https://github.com/tailwindlabs/headlessui/pull/3361))
- Fix outside click in nested portalled `Popover` components ([#3362](https://github.com/tailwindlabs/headlessui/pull/3362))
- Fix restoring focus to correct element when closing `Dialog` component ([#3365](https://github.com/tailwindlabs/headlessui/pull/3365))
- Fix `flushSync` warning for `Combobox` component with `immediate` prop enabled ([#3366](https://github.com/tailwindlabs/headlessui/pull/3366))

## [2.1.1] - 2024-06-26

Expand Down
37 changes: 31 additions & 6 deletions packages/@headlessui-react/src/components/combobox/combobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1321,12 +1321,37 @@ function InputFn<
if (!data.immediate) return
if (data.comboboxState === ComboboxState.Open) return

flushSync(() => actions.openCombobox())

// We need to make sure that tabbing through a form doesn't result in incorrectly setting the
// value of the combobox. We will set the activation trigger to `Focus`, and we will ignore
// selecting the active option when the user tabs away.
actions.setActivationTrigger(ActivationTrigger.Focus)
// In a scenario where you have this setup:
//
// ```ts
// {condition && (
// <Combobox immediate>
// <ComboboxInput autoFocus />
// </Combobox>
// )}
// ```
//
// Then we will trigger the `openCombobox` in a `flushSync`, but we are
// already in the middle of rendering. This will result in the following
// warning:
//
// ```
// Warning: flushSync was called from inside a lifecycle method. React
// cannot flush when React is already rendering. Consider moving this call
// to a scheduler task or micro task.
// ```
//
// Which is why we wrap this in a `microTask` to make sure we are not in the
// middle of rendering.
d.microTask(() => {
flushSync(() => actions.openCombobox())

// We need to make sure that tabbing through a form doesn't result in
// incorrectly setting the value of the combobox. We will set the
// activation trigger to `Focus`, and we will ignore selecting the active
// option when the user tabs away.
actions.setActivationTrigger(ActivationTrigger.Focus)
})
})

let labelledBy = useLabelledBy()
Expand Down

0 comments on commit 5fb738f

Please sign in to comment.