【问题标题】:Trouble updating Picker component from Async Storage in React Native从 React Native 中的异步存储更新 Picker 组件时遇到问题
【发布时间】:2020-10-06 00:59:24
【问题描述】:

我正在使用一个 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();
    }, []);

根据我对异步存储的有限了解,这似乎是有道理的。我觉得是

  • 等待从存储中获取值的结果
  • 设置状态
  • 渲染组件(这也可能在设置状态之前发生,但我认为它会在状态更改时再次渲染)
  • 当用户选择新选项时更新存储和状态

但是,这不起作用。如果我离开然后返回页面,则状态已重置。

更新:

如果我 console.log 在 onValueChange 异步函数中记录 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

或其他一些长串值,表明某处存在反馈循环。

【问题讨论】:

    标签: react-native expo asyncstorage


    【解决方案1】:

    您的表达式 AsyncStorage.setItem() 没有触发,因为您忘记在 onValueChange 的回调函数中调用自调用函数。

        onValueChange={(itemValue, itemIndex) => { 
            (async () => { 
                await AsyncStorage.setItem(`@circle_${circle.name}_frequency`, itemValue)
            })(); // I will invoke myself
            setFrequency(itemValue);
        }}
    

    已更新(更新问题后):

    我没有在您给定的 sn-p 代码中发现更多错误,我不知道您的完整源代码发生了什么。无论如何,我在您问题中的代码之后创建了一个超级简单的工作 sn-p 代码,因此您可以复制到您的项目中。

    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 标签,我只是想提醒一下,如果你在网络浏览器上预览项目,你的storedFrequencyuseEffect 中将永远是null,因为浏览器不支持AsyncStorage

    【讨论】:

    • 啊,谢谢!我错过了,但它不能解决核心问题。我会用更多信息更新线程。
    • 我也已经更新了答案,请查收。
    • 感谢您的帮助!在 Snack 上对此进行测试让我找到了答案。看起来这是 Picker 组件本身的问题。我赞成你的回答,但我没有足够的分数来显示它。
    【解决方案2】:

    看起来问题出在 Picker 本身以及它如何在每次渲染时调用 onValueChange 而不仅仅是在更改时。我在这个线程中找到了一个临时解决方案,直到它得到修复:https://github.com/lawnstarter/react-native-picker-select/issues/112#issuecomment-634038287

    【讨论】:

      猜你喜欢
      • 2017-01-10
      • 2022-11-16
      • 2020-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-18
      • 1970-01-01
      相关资源
      最近更新 更多