带有钩子反应的AsyncStorage不匹配数据在调试模式下是本地的

问题描述

我有2个独立的屏幕,分别与简单的React Native Stack路由器连接。在第二个屏幕上,我有选择块,其状态设置为useState以及AsyncStorage,在每次进入屏幕时,它还将每个条目上的AsyncStorage状态读取为useState钩子的初始状态。在第一个屏幕上,我具有导航到特定屏幕的列表块,在2个块中,语言和货币有“标签”,显示AsyncStorage的状态,这就是问题所在。我在useFocused钩子上调用了useEffect钩子,该钩子更新了此“标签”,在调试模式下可以正常工作,但是在没有调试模式的情况下,它会设置先前选择的值,在APK构建中具有相同的效果

这是第一个屏幕:

const ListLine = (props) => {
    return  <TouchableOpacity style={styles.line} onPress={props.onPress}>
                <View style={styles.line_text}>
                    {props.label ? <Text style={styles.label}>{props.label}</Text> : null}
                    {props.labelLong ? <Text style={styles.label_long}>{props.labelLong}</Text> : null}
                    {props.value ? <Text style={styles.line_title}>{props.value}</Text> : null}
                </View>
                <View style={styles.icon}><IconArR/></View>
            </TouchableOpacity>
}

const SettingsScreen = (props) => {

    const insets = useSafeArea();
    const {navigation} = props;
    const userInfo = useSelector(state => state.userInfoReducer)
    const dispatch = usedispatch()
    const [selectedCountry,setSelectedCountry] = useState(userInfo.country)
    const [selectedLanguage,setSelectedLanguage] = useState(null)
    const [selectedCurrency,setSelectedCurrency] = useState(null)
    const isFocused = useIsFocused()

    useEffect(() => {
      retrieveUserSettings().then(res => {
        let objRes = JSON.parse(res)
        setSelectedLanguage(objRes.language)
        setSelectedCurrency(objRes.currency)
        console.log(objRes,'useEffect res')
      })
    },[isFocused])

    useEffect(() => {
      dispatch(loadSettings())
    },[])

    useEffect(() => {
      setSelectedCountry(userInfo.country)
    },[userInfo])

    const retrieveUserSettings = async () => {
      return await AsyncStorage.getItem('userSettings')
    }

    return (
        <View style={styles.settingsScreen}>
           <View style={{paddingTop: insets.top,backgroundColor: '#0060C2'}}/>
            <AppBarlogo navigationlogo={()=>navigation.navigate('SearchScreen')}/>
            <ListLine label={'Country'} value={selectedCountry} onPress={()=>navigation.navigate(routes.selectCountry)}/>
            <ListLine label={'Language'} value={selectedLanguage} onPress={()=>navigation.navigate(routes.selectLanguage)}/>
            <ListLine label={'Currency'} value={selectedCurrency} onPress={()=>navigation.navigate(routes.selectCurrency)}/>
            <ListLine labelLong={'Terms and Confitions'} onPress={()=>navigation.navigate(routes.termsAndConditions)}/>
            <ListLine labelLong={'Privacy Policy'} onPress={()=>navigation.navigate(routes.privacyPolicy)}/>
            <ListLine labelLong={'Cookie Policy'} onPress={()=>navigation.navigate(routes.cookiePolicy)}/>
            <ListLine labelLong={'Notification Settings'} onPress={()=>navigation.navigate(routes.notificationSettings)}/>
        </View>
    )
}

export default SettingsScreen;

这是第二个:

const SelectCurrency = (props) => {
  const { navigation } = props;

  const currencies = useSelector(state => state.settingsReducer.data.currencies)
  const [selectedCurrency,setSelectedCurrency] = useState('Euro')

  useEffect(() => {
    retrieveUserSettings().then(res => setSelectedCurrency(JSON.parse(res).currency))
  },[])

  useEffect(() => {
    saveUserSettings()
  },[selectedCurrency])

  const retrieveUserSettings = async () => {
    return await AsyncStorage.getItem('userSettings')
  }

  const saveUserSettings = async() => {
    const storedData = await AsyncStorage.getItem('userSettings')
    const storedDataParsed = JSON.parse(storedData)
    const newData = { ...storedDataParsed,currency: selectedCurrency }
    await AsyncStorage.setItem('userSettings',JSON.stringify(newData))
  }

  const handleSelect = (currency) => () => {
    setSelectedCurrency(currency)
    navigation.goBack()
  }

  const renderList = () => {
    return Object.values(currencies).map((item,key) =>
    {
      return <TouchableOpacity
        style={styles.title_wrap}
        key={key}
        onPress={handleSelect(item.description)}>
        <View style={{...styles.title_wrap,marginBottom: 0,paddingHorizontal: 0}}>
          <Image style={styles.icon} source={{ uri: item.icon }}/>
          <Text style={styles.title}>{item.description}</Text>
        </View>
        <View style={{display: item.description === selectedCurrency ? 'flex' : 'none'}}><IconCheck/></View>
      </TouchableOpacity>
    })
  }

  return (
    <View style={styles.container}>
      <SafeAreaView style={styles.safeArea}/>
      <AppBararrow navigation={()=>navigation.goBack()} header={'Select Currency'}/>
      {renderList()}
    </View>
  )
}

export default SelectCurrency

SelectCurrency屏幕和SelectLanguage相同

这是带有圆圈的“标签”的屏幕的外观,也许会有所帮助

enter image description here

解决方法

如果您遇到相同的问题,这可能不是最佳解决方案,但它可以工作。只需将isFocused挂钩上的useEffect修改为此:

useEffect(() => {
      const timer = setTimeout(() => {
        retrieveUserSettings().then(res => {
          let objRes = JSON.parse(res)
          setSelectedLanguage(objRes.language)
          setSelectedCurrency(objRes.currency)
        })
      },1);
      return () => clearTimeout(timer);
    },[isFocused])