I want to support localization using react-18next.
This component shows a Picker
, sets a LocalStorage key (the selected language) and change the app language.
I noticed the onValueChange
method is called twice. The first call (using a proper selection tap action on a Picker item) have the correct parameter (the language I have chosen), the second call have the value of the first Picker item, whenever the values is (!).
Example: if I select the English
Picker item, I see the Picker switch to English (first _changeLanguage()
call), and then again to "Device" (second _changeLanguage()
call). I'm sure it's an async ops problem, not sure where..
@translate(['settings', 'common'], { wait: true })
export default class Settings extends Component {
state = {};
constructor(props) {
super(props);
}
componentWillMount() {
this.getLang();
}
async _changeLanguage(ln) {
const { t, i18n, navigation } = this.props;
console.warn("_changeLanguage: ",ln)
await this.promisedSetState({lang:ln})
if(ln=="device") {
console.warn("removing lang setting")
await AsyncStorage.removeItem('@App:lang');
} else {
console.warn("lang setting: ", ln)
await AsyncStorage.setItem('@App:lang', ln);
i18n.changeLanguage(ln)
}
};
//get Language from AsyncStorage, if it has been previously set
async getLang() {
const value = await AsyncStorage.getItem('@App:lang');
console.warn("getLangfrom asyncstorage:", value)
if(value) await this.promisedSetState ({lang:value})
}
promisedSetState = (newState) => {
return new Promise((resolve) => {
this.setState(newState, () => {
resolve()
});
});
};
render() {
const { t, i18n, navigation } = this.props;
const { navigate } = navigation;
return (<View>
<Picker
selectedValue={this.state.lang}
onValueChange={(itemValue, itemIndex) =>this._changeLanguage(itemValue) }>
<Picker.Item color="#666" label="detected from device" value="device" />
<Picker.Item label="English" value="en" />
<Picker.Item label="Deutsch" value="it" />
</Picker>
</View>);
}
}
The code is based on the react-i18next Expo example https://github.com/i18next/react-i18next/tree/master/example/v9.x.x/reactnative-expo
I'm not sure if this belongs here but if anyone is encountering the problem of onValueChange
firing twice and is using react-native-picker-select
instead of the default Picker
then this solution may work for you.
I ended up using the itemKey
property instead of value
and setting the key of each item to be the same as its value. Note the example item would end up shaped like so: { key: 'value1', value: 'value1', label: 'Your Label' }
where the key
and value
are identical.
Original Code:
<RNPickerSelect
style={styles.picker}
value={value}
onValueChange={this.onValueChange}
placeholder={placeholder}
items={options}
/>
Fixed Code:
<RNPickerSelect
style={styles.picker}
itemKey={value}
onValueChange={this.onValueChange}
placeholder={placeholder}
items={options}
/>
I got my inspiration from this: GitHub issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With