picker icon indicating copy to clipboard operation
picker copied to clipboard

select lead to infinite loop on android, when using together with recoil

Open wtlyu opened this issue 3 years ago • 1 comments

Example Code:

  const [selectedLanguage, setSelectedLanguage] = useRecoilState(globalStore.selectedLanguage)

  <Picker
    style={[styles.formitem_value, styles.formitem_picker]}
    selectedValue={selectedLanguage}
    onValueChange={(itemValue, itemIndex) => setSelectedLanguage(itemValue)}>
    <Picker.Item label='Java' value='java' />
    <Picker.Item label='JavaScript' value='js' />
  </Picker>

This will lead to infinite loop between two items. I have added some debug code when picker receive a onSelect event from native code, and I got those:

 LOG  new onSelect event
 LOG  props.selectedValue is java
 LOG  children[position].props.value is js                <<< Current is java and user select js.
 LOG  new onSelect event                                  <<< The state has changed, and this is triggered when re-render
 LOG  props.selectedValue is js                           <<< Current is now js, that's expected.
 LOG  children[position].props.value is java              <<< Why this become java??? that's expected to be js also.
 LOG  new onSelect event                                  <<< Stating from this line, is infinite state change and infinite loop...
 LOG  props.selectedValue is java
 LOG  children[position].props.value is js
 LOG  new onSelect event
 LOG  props.selectedValue is js
 LOG  children[position].props.value is java
 LOG  new onSelect event
 LOG  props.selectedValue is java
 LOG  children[position].props.value is js
 LOG  new onSelect event
 LOG  props.selectedValue is js
 LOG  children[position].props.value is java
 LOG  new onSelect event
 LOG  props.selectedValue is java
 LOG  children[position].props.value is js
 LOG  new onSelect event
 LOG  props.selectedValue is js
 LOG  children[position].props.value is js
....., infinite output

It seems something conflict with the trigger of onSelect event, the position attribute changes without any user action. (it seem that onSelect will be called when Picker re-rendering, but children[position].props.value get a strange result.)

Platform

Android 11 React Native 0.68.2 recoi 0.5.0 @react-native-picker/picker tested on 2.0.1 and 2.4.1

wtlyu avatar Jun 08 '22 10:06 wtlyu

FYI, globalStore in code is a module that holds all recoil atoms. like this:


const selectedLanguage = atom({
  key: 'selectedLanguage',
  default: 'js'
})

wtlyu avatar Jun 08 '22 10:06 wtlyu