AsyncStorage 不匹配数据与钩子在调试模式下本机反应

AsyncStorage mismatch data with hook react native in debug mode

我有 2 个单独的屏幕与简单的 React 本机堆栈路由器相连。在第二个屏幕上,我有选择块将状态设置为 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

选择货币屏幕和选择语言相同

这是带圆圈“标签”的屏幕显示,也许会有帮助

如果您遇到同样的问题,这可能不是最佳解决方案,但它确实有效。只需将 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])