-
Notifications
You must be signed in to change notification settings - Fork 24.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Android Picker Not Consistently Firing onValueChange #15556
Comments
I am currently experiencing this error too, with about the same 33% statistic. |
I also have exactly the same problem. Any solutions / workarounds? |
Unfortunately I have the same problem. Has anyone found any solution to resolve this behavior? Or at least an workaround. |
+1 encountering this bug in two separate applications. happens about every other selection |
+1 seeing the exact same thing :(. any workarounds to this problem? |
+1 Unbelievable that this error occurs. Do I have to try and rewrite my app not using the Picker just so that it will reliable? Crazy world. Any workarounds would be appreciated. |
did you try adding a state? demo: https://snack.expo.io/r1JfNfKRZ |
Still happening in 0.49. Honestly this Picker component should be removed from the doc or marked as "alpha", as it simply doesn't work and shouldn't be relied on. If I had known from the start that it was broken, I could have used a third party picker or make my own. |
Can anyone point to a related commit that might have broken this? I can probably look at this if someone can point me in the right direction |
+1 |
FYI: tested on 'left hand'/'right hand' example above and this appears to be fixed on master; no idea which commit actually fixed it |
+1 any workaround for this? |
+1 Any temporary workaround around this problem ?? |
Same problem. |
@tombailey any chance you are able to figure out what the commit was so it can be proposed for the next release? adding |
@ThaJay I have looked but I have no idea which commit resolved this. I didn't do an upgrade on my project, I just created a new one with the example above and pointed at the latest version of RN. Can someone else verify it works for them too? |
I just made a test project and was unable to reproduce: If I remove |
Further testing learns that the behavior does not change on the latest version (v0.50.4) As stated above I was unable to reproduce this in an empty project but I'm still stunned as of how this can happen and it's a blocking bug for the next release that's waiting to be approved. The example OP gives does not work, the
|
I added redux to the test repo and was still unable to reproduce |
@ThaJay given that this is Android specific and seems to happen 50% of the time, I am inclined to blame https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPicker.java#L133 mSuppressNextEvent in particular I don't have the time to look at this properly so if anyone else does that would be great. |
If I disable So there must be something going wrong with the re-render |
I have found the folowing workaround using constructor (props) {
super(props)
this.state = {value:this.props.eventId}
}
componentDidUpdate () {
if (
this.state.value &&
this.props.eventId !== this.state.value
) {
this.props.chooseEvent(this.state.value)
}
}
onValueChange = value => {
this.setState({value})
} with <Picker
selectedValue={this.state.value}
onValueChange={this.onValueChange}
> |
This issue still happening until this days... unbelievable! |
+1 fix for this. The same issue with Android Picker. |
For anyone still having issues with this, you might be interested in https://github.com/tombailey/react-native-fixed-android-picker as a work around |
I found a solution. I my case i was using redux-form. something like.. Note this lines: constructor(props) {
super(props);
this.state = { itemValue: this.prop.initialSelectedValue };
}
render () {
const {
input: { value, onChange, ...inputProps },
} = this.props;
return (
<Picker
selectedValue={this.state.itemValue}
onValueChange={itemValue => {
this.setState({ itemValue });
onChange(itemValue);
}}
{...inputProps}
>
);
} Cheers |
I struggled with this problem during several hours and @diegolaciar 's workaround works ! It may be related how the Picker handles the render process, and in which order it updates its internal selected value. Well, at least we have a workaround now :) Thanks again diego |
It seems you should add |
@AliaMYH Take a look at my example too, both this.state and this.setState are needed to make it work. Anything else does not work. Props do not work. |
I working on React Native v0.54.0, this bug still appeared, the action onValueChange on Android does not fire when the user selected the first item on the picker. |
I'm on react-native 0.55.0 and the issue is back even with my workaround. What do I do now? :/ |
@ThaJay until the root cause is determined and fixed, you probably want to try #15556 (comment) |
@tombailey I had a similar workaround in place. #15556 (comment) |
@ThaJay the solution I posted isn't a "workaround" in the same way your's was. It does actually what you propose "TouchableOpacity and a Modal with a list". |
@tombailey Oh sorry, I thought you meant @diegolaciar's post below yours. That contains the same workaround. Your repo is indeed similar to what I built yesterday. It's nice to have control over styling, isn't it? Finally my picker dialog is dark in night mode. 👍 |
@hramos , can you reopen this issue? |
I find this line
Can we start with selectedIndex = -1 ? |
I have the same issues. I think this issues should be reopen. Thank you very much |
I use setTimeout to achieve it, it's a bit tricky but it works
|
Folks, I think it should be used with state instead of props like |
It helped, thanks. |
@hafizalfaza Youu solution worked although i just needed to use: I really don't understand how this works fine but the picker doesn't work well. my react-native version i s 0.57 |
For people revisiting, @hafizalfaza 's solution is the way to go. Picker's onValueChange needs setTimeout or some other way of adding to event loop to work correctly |
Why is this even closed? Issue is still exist, @hafizalfaza 's solutions isn't that I really want to use in my life |
Then don't use it. I have had a different Picker component in my app for ages. This is not likely to get fixed any time soon. edit: LOL 1 day later it got fixed |
What do you recommend @ThaJay ? |
I made my own. I think there was someone in this thread who made his own and published it as a module, but I just made a gist out of my code as an example of how this could be done. I just pasted 2 files together and removed duplicate imports so it will not work as is, but maybe you can use parts of it in your own project. |
…ondition (#22821) Summary: Changelog: ---------- [Android] [Fixed] - Fix Picker.onValueChange sometimes not fired due to race condition. Fixes #15556 Root Cause: ------------ Please check my code snippet at https://snack.expo.io/kudochien/android-picker-issue and try to select different items on Picker to see if console.log() hit. If calling setState() with some latency, e.g. setTimeout() or changes from redux, the second time changing picker item on UI, the onValueChange() will be not fired. The root cause comes from the `forceUpdate` in PickerAndroid.android.js. If user's setState() update comes after forceUpdate(), the flow will be: 1. First time select picker item 2. onValueChange + forceUpdate 3. user's setState() + componentDidUpdate + setNativeProps({ selected: ... }) 4. mSuppressNextEvent = true 5. Second time select picker item 6. Since mSuppressNextEvent is true, the onValueChange will not be fired. Solution: --------- Like other controlled components, disable change listener during setup values from JS. Android Spinner `setSelection(int position)` is asynchronous call, i.e. will fire onItemSelected in next run loop and is not suitable for us. `setSelection(int position, boolean animate)`, however, is synchronous call which I used. Some more references about setSelection: https://stackoverflow.com/a/43512925/2590265 http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/widget/AbsSpinner.java#276 The two arguments version will use `setSelectionInt()` which set mBlockLayoutRequests as true to prevent onItemSelected call from next layout(). I also moved the setOnItemSelectedListener() call after onLayout to prevent onValueChange() during intialization. Pull Request resolved: #22821 Differential Revision: D13731979 Pulled By: cpojer fbshipit-source-id: e06bd9aa62463b66c8f3fd7214485898d5375054
…ondition (facebook#22821) Summary: Changelog: ---------- [Android] [Fixed] - Fix Picker.onValueChange sometimes not fired due to race condition. Fixes facebook#15556 Root Cause: ------------ Please check my code snippet at https://snack.expo.io/kudochien/android-picker-issue and try to select different items on Picker to see if console.log() hit. If calling setState() with some latency, e.g. setTimeout() or changes from redux, the second time changing picker item on UI, the onValueChange() will be not fired. The root cause comes from the `forceUpdate` in PickerAndroid.android.js. If user's setState() update comes after forceUpdate(), the flow will be: 1. First time select picker item 2. onValueChange + forceUpdate 3. user's setState() + componentDidUpdate + setNativeProps({ selected: ... }) 4. mSuppressNextEvent = true 5. Second time select picker item 6. Since mSuppressNextEvent is true, the onValueChange will not be fired. Solution: --------- Like other controlled components, disable change listener during setup values from JS. Android Spinner `setSelection(int position)` is asynchronous call, i.e. will fire onItemSelected in next run loop and is not suitable for us. `setSelection(int position, boolean animate)`, however, is synchronous call which I used. Some more references about setSelection: https://stackoverflow.com/a/43512925/2590265 http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/widget/AbsSpinner.java#276 The two arguments version will use `setSelectionInt()` which set mBlockLayoutRequests as true to prevent onItemSelected call from next layout(). I also moved the setOnItemSelectedListener() call after onLayout to prevent onValueChange() during intialization. Pull Request resolved: facebook#22821 Differential Revision: D13731979 Pulled By: cpojer fbshipit-source-id: e06bd9aa62463b66c8f3fd7214485898d5375054
This issue still reproduces. Picker does not trigger |
Guys, I solved this problem with unselectable first item by setting fake unselectable item with value = -1. Then when user picks valid item,fake item with value = -1 dissapears.
|
following code working fine on android but in "onValueChange" this.changeCityArray() not calling on IOS platform please help..... <Select |
Great! A little bit tricky but it works xd |
Empty value is prepended to Picker by library mainters in PickerModal.js to fix this issue: facebook/react-native#15556
Is this a bug report?
Yes. I have also seen this issue on stackoverflow.
Have you read the Contributing Guidelines?
Yes
Environment
react-native -v
: 2.0.1node -v
: v8.0.0npm -v
: 5.0.0yarn --version
: 0.24.5Steps to Reproduce
Using the Picker component in Android, the first
onValueChange
fires, but the next one does not. The one after does...this continues and results in about 33% of the timeonValueChange
does not fire.I created a snack with a basic example.
Expected Behavior
I expected
onValueChange
to fire if the Picker item selected is different from the current selection.Actual Behavior
About 33% of the time
onValueChange
will not fire, but the text on the Picker does change, which is confusing to the user. The other times, everything works as expected.Reproducible Demo
I created a snack with a basic example. Select one option, then another and, in my experience, it will not consistently log to console.
The text was updated successfully, but these errors were encountered: