Difference between `selectedItem` and `inputValue` is confusing
See original GitHub issuedownshift
version: 1.18.0node
version: 8.2.1npm
(oryarn
) version: 5.5.1
Issues is probably not the best place for this, but I wanted to log if before I forget. Feel free to close this soon though and/or put it somewhere more appropriate.
I want to control the inputValue
myself, so I started using the inputValue
and onInputValueChange
props. But I found a case where it didn’t behave as expected. In my code, I save the initial value of the input, and regardless of what the user has entered since then, pressing Escape should reset the input to the initial value I’ve saved.
I implemented this (it’s actually a common behavior across all my inputs, so it didn’t take any extra work). The problem is that pressing Escape would clear out the input. Debugging it showed that pressing Escape would run my code which resets it to the initial value, but immediately after Downshift first onInputValueChange
with an empty string, which clears it out.
Turns out Downshift resets the state when you press Escape, and part of that resetting is setting the input value to the selected value. But since I didn’t provide a selectedItem
prop, it resets it to an empty string.
The solution is to use the selectedItem
prop instead of inputValue
like this:
<Downshift
onChange={onUpdate}
selectedItem={value}
onInputValueChange={value => onUpdate(value)}
defaultHighlightedIndex={0}
>
This all works, but it feels asymmetric (why do I pass value down as selectedItem
but I’m listening to the inputValue?). It’s confusing exactly what the difference is between selectedItem
and inputValue
prop. I don’t have enough awareness of what the difference actually is so I don’t know what the solution is. Just wanted to give some feedback while I’m working with it.
Feel free to simply take this feedback and close this issue with nothing actionable.
Issue Analytics
- State:
- Created 6 years ago
- Reactions:2
- Comments:6 (6 by maintainers)
Top GitHub Comments
Hi @jlongster!
I’m thrilled you’re using downshift. I’m sorry and agree that
inputValue
andselectedValue
are confusing. I’m going to describe things a little bit despite the fact that you probably understand lots of this just for the benefit of others and to make things more clear.Here’s a brief definition of the two props:
selectedItem
: the current item that the user has selected. This happens when the user performs a “selection action” (click, or enter when an item is highlighted) on one of the items you render (withgetItemProps()
).inputValue
: the value the user has typed, or the stringified version ofselectedItem
as defined byitemToString
(defaults to casting theselectedItem
as a string).Unlike regular
<input />
s, the more common use case for components like downshift is to not change the selection when the user types, but wait until the user makes a “selection action.” In addition, the value that appears in the input is often a string-based representation of a more complex value (an object). Because of these qualities, we need to store the two states ofselectedItem
andinputValue
separately.The
onInputValueChange
(and theonStateChange
) function simply calls your callback with what it suggests you update your state to based on downshift’s semantics. Similar to how theonChange
callback works on an<input />
, they’re simply letting you know what downshift would update the value to if it were in control of the state itself.Now, to address the
Escape
key problem, you might try this… One of the lesser-known features of the way downshift composes your event handlers together is how it behaves differently when you callevent.preventDefault()
. For any events that are doing something you don’t like, you can pass your own event handler and callevent.preventDefault()
and that will prevent downshift’s default behavior as well.You can see this in action here. And you can see the code for this here:
https://github.com/paypal/downshift/blob/0d78347a2a424f55c10f30eb77d52d2f7b76a017/src/utils.js#L127-L141
If you could make a codesandbox of your solution, I might be able to help improve the solution and it could reveal some areas of clarification we could make in the documentation.
Thanks again!
By the way, generally it was nice that this is super flexible and it was easy to make it do exactly what I wanted once I started controlling state and overriding events. Thanks for making it so flexible!