react-native-picker-select: onValueChange Event triggers every time render update
Describe the bug Picker has function prop “onValueChange” as per expectation it should work like click event, when ever someone select value, but i found this event execute all the time when render() updates, so it creating problem, because it null my state value.
To Reproduce onValueChange = { (value) => console.log(“Event Triggered”+value)} Monitor console, it will execute all the time whenever render() update by any state or prop change.
Expected behavior It should execute only when we change dropdown value, after pick , not all the time
Smartphone (please complete the following information):
- Device: OnePlus2
- OS: Android
- react-native-picker-select version: 5.1.10
- react-native version: 0.55.4
- react version: 16.3.1 Reproduction and/or code sample
<PickerSelect
value={formData['country']}
placeholder={{label: I18n.t('select'), value: ''}}
style={pickerStyle}
onValueChange={(itemValue,itemIndex) => {
console.log("Country index="+itemIndex);
console.log("Country current="+formData['country']);
console.log("Country Changed="+itemValue);
this.handleChangeValue(itemValue,"country","picker")
}}
items={COUNTRY_RENDER}
/>
Once select country i set in state using “handleChangeValue” formData[‘country’] Whenever i change language it update my render() I tried to debug
console.log("Country index="+itemIndex);
console.log("Country current="+formData['country']);
console.log("Country Changed="+itemValue);
this.handleChangeValue(itemValue,"country","picker")
formData[‘country’] always return my selected country, but console.log(“Country Changed=”+itemValue);
does not return selected index once, i change language.
If language value is same for both english and spanish language, then it should return same index
About this issue
- Original URL
- State: open
- Created 6 years ago
- Reactions: 37
- Comments: 65 (1 by maintainers)
Commits related to this issue
- controlled component thanks to https://github.com/lawnstarter/react-native-picker-select/issues/112#issuecomment-452924222 — committed to simpleTechs/react-native-picker-select by EyMaddis 5 years ago
- Add fixes that were suggested in issue #112 — committed to Silverchip-Labs/react-native-picker-select by deleted user 5 years ago
I’ve fixed it for me by adding key parametr to RNPickerSelect like this
P.S. I use Mobx state management
I tried all other solutions, but finally this did the job for me! Thanks @SmirnovM91
Set the key prop to the same state value as the value prop… how weird!
… key={this.state.country} value={this.state.country} …
Had the issue only on Android, using: “@react-native-picker/picker”: “^1.9.8” “react-native-navigation”: “^7.0.0”
If you want a very cheap, shameful and dirty solution (but working nonetheless). You can validate that the value has been changed by the user if the value has been changed x milliseconds (in that case 100 ms) after the component has been mounted (because the user won’t have enough time to click the element and select a value in such a short time). I tested it and it’s working on Android, iOS and web. You should however wash your hands after using that hack 😬 :
I fixed mine by turning it into a controlled component like most of the other react-native components so rendering is only driven by props with not state memory. This actually simplifies a number of interactions.
you can solve by using if condition in on value change
like this
Using react-native-picker-select@8.0.4, react-native@0.63.2.
Can confirm the following works without the issue:
As soon as I remove the key property, i get multiple console.logs (multiple re-renders) as I change values, so I can confirm the key property fix the issue.
PS: Using functional components, and useState hook for pickerValue,setPickerValue
I’m seeing the same issue but am unable to reproduce via snack.expo.io. I observed the following sequence:
I worked around this by removing the call nextProps.onValueChange(selectedItem.value, idx); from getDerivedStateFromProps.
Checking to see if there are any fixes for this bug?
Ive just switched to
7.0.0-beta.0
for my Expo + Redux project and I’m getting the same bug.If anyone is still having this issue, I’d like to add my two cents. I was having the same issue and somehow I solved it by changing the type of value in the items list. Using value as a number was triggering the render for me but, when I changed value to string, the problem stopped.
items={[ { label: “option 1”, value: “USE STRING INSTEAD OF NUMBER” }, ]}
Hope it helps
version: “react-native-picker-select”: “^8.0.4”; I fixed this problem like this:
const [valuePicker, setValuePicker] = useState(‘’); return ( <PickerSelect placeholder={{label: ‘some text’, value: ‘’ }} items={items} value={valuePicker} onValueChange={(v) =>{ if (v !== valuePicker){ setValuePicker(v); } }} /> )
Just adding my experience here if it helps someone:
I’m trying to make the Picker only emit its value when Done is pressed. To do this I stored the index of the selected item and call
onValueChange
inonDone
instead. My issue was the placeholder item this library inserts at the front of the items, this caused myonValueChange
to be called repeatedly, iterating through theitems
array.The solution for me was to set the placeholder prop to an empty object. This disables the initial “label” that is shown at the top and prevents this infinite renders issue.
Another solution for this would probably be to emit an onChange event for
index-1
instead if the placeholder is present.I am using the beta version 7.0.0-beta.0. It did fix an issue with the dropdown changing the values a couple times before going back to the correct value.
In the onValueChange I still have to check if the value does not equal the new one using an if statement, otherwise it results in an infinite loop. That is still a bug should be addressed. In other pickers there is no need for the if statement.
onValueChange={(value, index) => { if (value != this.state.value) this.valueChanged(value, index-1); }}
Also, when there is a placeholder, it gets included in the array of values, so the index needs to be adjusted by -1. That should probably not be the case either.
It happened for me whenever I
setState
inside a promise ononValueChange
:Example:
Whenever I change the value of the picker one time, the function
handleStateChange
is triggered twice.@jpandl19 @glenne i’m going to release a version with a prop to disable that. should resolve the issue for now and then we can look into it further in the future.