问题描述
我正在使用Picker组件让用户设置一个值,该值表示他们想被提醒某件事的频率。在下面的代码中,我将结果保存为组件状态,并通过异步存储将其保存到设备中:
const [frequency,setFrequency] = useState('year');
...
<Picker
selectedValue={frequency}
style={styles.picker}
itemStyle={styles.pickerItem}
onValueChange={(itemValue,itemIndex) => {
(async () => {
await AsyncStorage.setItem(`@circle_${circle.name}_frequency`,itemValue)
})();
setFrequency(itemValue);
}}
mode={'dropdown'}
prompt={'Reminder every:'}
>
<Picker.Item label="Never" value="never" />
<Picker.Item label="Day" value="day" />
<Picker.Item label="Week" value="week" />
<Picker.Item label="Year" value="year" />
etc...
</Picker>
我还希望组件抓取保存的数据并将其设置为首次渲染时的状态。
useEffect(() => {
const fetchFrequency = async () => {
let storedFrequency = await AsyncStorage.getItem(`@circle_${circle.name}_frequency`);
if (storedFrequency != null) {
setFrequency(storedFrequency);
};
}
fetchFrequency();
},[]);
基于我对异步存储了解的有限数量,这似乎是有道理的。我认为是
但是,这不起作用。如果我导航离开然后返回页面,则状态已重置。
更新:
如果我在onValueChange异步函数中console.log itemValue,这就是我得到的:
onValueChange={(itemValue,itemIndex) => {
(async () => {
await AsyncStorage.setItem(`@circle_${circle.name}_frequency`,itemValue)
console.log(itemValue)
})();
setFrequency(itemValue);
}}
将值更改为“从不”时,它会打印
never
never
当我导航离开然后返回时,甚至不触摸组件就会打印出来:
week
week
never
never
year
year
或
year
never
year
year
或其他一些长字符串,表明某处正在进行反馈循环。
解决方法
您的表达式AsyncStorage.setItem()
未触发,因为您忘记了在onValueChange
的回调函数中调用自调用函数。
onValueChange={(itemValue,itemIndex) => {
(async () => {
await AsyncStorage.setItem(`@circle_${circle.name}_frequency`,itemValue)
})(); // I will invoke myself
setFrequency(itemValue);
}}
已更新(在更新后的问题之后):
在您指定的代码段中,我再也没有发现任何bug,也不知道完整的源代码是怎么回事。无论如何,我创建了一个超级简单的工作片段代码,后面是您问题中的代码,因此您只需将其复制到您的项目中即可。
import React,{useState,useEffect} from 'react';
import {Picker,AsyncStorage} from 'react-native';
export default function App() {
const [frequency,setFrequency] = useState('year');
useEffect(() => {
const fetchFrequency = async () => {
let storedFrequency = await AsyncStorage.getItem('@circle_circle_name_frequency');
if (storedFrequency != null) {
setFrequency(storedFrequency);
}
};
fetchFrequency();
},[]);
return (
<Picker
selectedValue={frequency}
onValueChange={(itemValue,itemIndex) => {
(async () => {
await AsyncStorage.setItem('@circle_circle_name_frequency',itemValue);
})();
setFrequency(itemValue);
}}
mode={'dropdown'}
prompt={'Reminder every:'}>
<Picker.Item label="Never" value="never" />
<Picker.Item label="Day" value="day" />
<Picker.Item label="Week" value="week" />
<Picker.Item label="Year" value="year" />
</Picker>
);
}
希望这会有所帮助!
PS:我看到您在问题上加上了expo
标记,我想提醒一下,如果您在网络浏览器上预览项目,则storedFrequency
中的useEffect
将始终是null
,因为浏览器不支持AsyncStorage
。
问题似乎出在Picker本身及其如何在每个渲染上调用onValueChange而不是仅在更改时出现问题。我在此线程中找到了一个临时解决方案,直到它解决为止:https://github.com/lawnstarter/react-native-picker-select/issues/112#issuecomment-634038287