Reach-ui: ComboboxInput Does not accept an external value

Created on 28 Sep 2020  ·  3Comments  ·  Source: reach/reach-ui

🐛 Bug report

Current Behavior

I use React hook state to store value.

<Combobox
    openOnFocus
    onChange={event => setValue(event.target.value)}
    onSelect={item => setValue(item)}
    value={know}
>
    <ComboboxInput
        placeholder="placeholder"
        autocomplete
        className="input"
    />
    <ComboboxPopover>
        <ComboboxList>
            <ComboboxOption value="Hello" />
            <ComboboxOption value="Biiiig" />
        </ComboboxList>
    </ComboboxPopover>
</Combobox>

Expected behavior

Reproducible example

CodeSandbox Template

Suggested solution(s)

Additional context

Your environment


plz, make bash command how this print? Write it in this template

| Software | Name(s) | Version |
| ---------------- | ------- | ------- |
| Reach Package | | |
| React | | |
| Browser | | |
| Assistive tech | | |
| Node | | |
| npm/yarn | | |
| Operating System | | |

Most helpful comment

Hey @indiesquidge! We're running into an issue with this implementation. When you add the controlled value prop to the input, it causes the popover to stay open when you select a value. Here's a basic repro: https://codesandbox.io/s/intelligent-payne-0u1xp

We're trying to work around the same case as in #502, where we want to have the displayed be different from what data we want to use (in this case, display a name, but use the related ID. there can be duplicate values in the ComboboxList, but those are made clear to the user using a custom Combobox option). More than happy to open a PR, it looks like there's one open for #502, and handling just this would be at odds with the keyboard handling.

All 3 comments

Hey @higimo! Can you provide a bit more detail on what your issue is and what you expect the behavior to be?

By the looks of the snippet you included (and your CodeSandbox), you've included the onChange and value prop on the Combobox component, but you'll want to put those on the input, same as you would with a native React input. Check out the Combobox docs for more details on the props for the different parts of this compound component.

<Combobox
    openOnFocus
-       onChange={event => setValue(event.target.value)}
    onSelect={item => setValue(item)}
-       value={know}
>
    <ComboboxInput
        placeholder="placeholder"
        autocomplete
        className="input"
+               onChange={event => setValue(event.target.value)}
+               value={know}
    />
    <ComboboxPopover>
        <ComboboxList>
            <ComboboxOption value="Hello" />
            <ComboboxOption value="Biiiig" />
        </ComboboxList>
    </ComboboxPopover>
</Combobox>

Hey @indiesquidge! We're running into an issue with this implementation. When you add the controlled value prop to the input, it causes the popover to stay open when you select a value. Here's a basic repro: https://codesandbox.io/s/intelligent-payne-0u1xp

We're trying to work around the same case as in #502, where we want to have the displayed be different from what data we want to use (in this case, display a name, but use the related ID. there can be duplicate values in the ComboboxList, but those are made clear to the user using a custom Combobox option). More than happy to open a PR, it looks like there's one open for #502, and handling just this would be at odds with the keyboard handling.

Hi @mgostisha, I may be misunderstanding your issue … can you explain how #502 is related to what you're trying to do here?

The idea of #502 is about passing custom data from ComboboxOption to the onSelect handler, but your example sandbox does not have custom option data. You have a ComboboxInput with a null initial value (i.e. it's telling Reach that you want to treat the input as uncontrolled), a no-op input change handler (continuing the intent of having an uncontrolled component), but then attempts to change that uncontrolled value programmatically (i.e. in a _controlled_ way) based on an option selection.

Notice in your example that wiring things up this way, the user is initially able to type anything they want in the input (because at this point its an uncontrolled input … how you'd get back the user's input if they didn't select an option isn't clear). If the user does decide to select one of the options, you programmatically update the input value, telling Reach you actually want to control this value yourself now, which breaks the input. The user is no longer able to type or delete.

Was this page helpful?
0 / 5 - 0 ratings