Downshift: defaultInputValue doesn't update when props change

Created on 21 Jun 2018  路  3Comments  路  Source: downshift-js/downshift

  • downshift version: 2.0.7
  • node version: 8.11.1
  • npm (or yarn) version: 6.0.1

Relevant code or config

const CountrySelect = props => (
  <Downshift
    onSelect={props.selectCountryAction}
    defaultSelectedItem={props.selectedCountry}
    itemToString={item => item.name}
  >
// ...

What you did:

We are storing the selected item (country) in our Redux state. This is initially populated on the server (via query string) and passed to Downshift via defaultSelectedItem. If the user changes their country using Downshift we dispatch an action to update this in the Redux state.

We are also persisting this Redux state in localStorage, so if the user refreshes the page everything renders with the initial state, then updates to show their previously entered details (we load from localStorage in componentDidMount).

What happened:

The problem is that although our Redux state updates to whatever the localStorage version of the selected country is (and correctly updates Downshift's props), Downshift doesn't seem to update its internal state. So the selected item is correctly set to the localStorage value, (as is the defaultSelectedItem prop), but the actual inputValue in Downshift's state is mismatched鈥攊t gets stuck on whatever value it was initially rendered with.

It seems like maybe #101 wasn't actually fixed?

Reproduction repository: https://codesandbox.io/s/r5w1x035xp

Suggested solution:

It's possible we're abusing the concept of "default" values. It feels like maybe if we want to keep Downshift in sync with our Redux store we would be better off making it a fully controlled component?

Otherwise is there any reason for Downshift not to update its internal state when it re-renders with new props?

help wanted question

Most helpful comment

@oliverjam I'll just give a piece of my opinion on this. From what you described and showed in codesandbox, It seems like you want to update defaultSelectedItem. However, if you look at the documentation, defaultSelectedItem is only meant to assign the initial value to Downshift. Essentially, defaultSelectedItem is only used in the constructor of Downshift, as below:
https://github.com/paypal/downshift/blob/e76224815ba2b62f843c14041984d3b421a62b24/src/downshift.js#L121-L128
So, this indicates that you only want to leverage defaultSelectedItem (same applied to all defaultXXX props, where XXX is any control prop) iff you want Downshift to be uncontrolled. However, in your case, you clearly want it to be controlled.
So, my advice would be to leverage selectedItem control prop, and sync that with your store.

All 3 comments

@oliverjam I'll just give a piece of my opinion on this. From what you described and showed in codesandbox, It seems like you want to update defaultSelectedItem. However, if you look at the documentation, defaultSelectedItem is only meant to assign the initial value to Downshift. Essentially, defaultSelectedItem is only used in the constructor of Downshift, as below:
https://github.com/paypal/downshift/blob/e76224815ba2b62f843c14041984d3b421a62b24/src/downshift.js#L121-L128
So, this indicates that you only want to leverage defaultSelectedItem (same applied to all defaultXXX props, where XXX is any control prop) iff you want Downshift to be uncontrolled. However, in your case, you clearly want it to be controlled.
So, my advice would be to leverage selectedItem control prop, and sync that with your store.

Yeah you're right. I guess it just felt weird because we weren't _really_ controlling it until we started persisting the value in localStorage.

It makes that that default props only set initial values, thanks!

I LOVE YOU @franklixuefei

Was this page helpful?
0 / 5 - 0 ratings

Related issues

klapouchy picture klapouchy  路  4Comments

glockjt picture glockjt  路  3Comments

alexandernanberg picture alexandernanberg  路  4Comments

Vincent-Alibert picture Vincent-Alibert  路  4Comments

jlongster picture jlongster  路  4Comments