picker
picker copied to clipboard
select lead to infinite loop on android, when using together with recoil
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
FYI, globalStore in code is a module that holds all recoil atoms. like this:
const selectedLanguage = atom({
key: 'selectedLanguage',
default: 'js'
})