Несоответствие данных AsyncStorage с hook react native в режиме отладки

#javascript #reactjs #react-native #asyncstorage

#javascript #reactjs #react-native #asyncstorage

Вопрос:

У меня есть 2 отдельных экрана, подключенных к простому маршрутизатору стека react native. На втором экране у меня есть блоки выбора с настройкой состояния на useState, а также на AsyncStorage, при каждом входе на экран, также он считывает состояние AsyncStorage при каждой записи как начальное состояние useState hook. На первом экране у меня есть блоки списка, которые переходят к определенному экрану, в 2 блоках языка и валюты у меня есть «метка», которая показывает состояние из AsyncStorage, и вот в чем проблема. У меня есть хук useEffect, вызываемый на хук useFocused, который обновляет эти «метки», он отлично работает в режиме отладки, но без режима отладки он устанавливает предыдущее выбранное значение, тот же эффект в сборке 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
  

Экран выбора валюты и SelectLanguage одинаковы

вот как это выглядит на экранах с обведенными «ярлыками», может быть, это поможет введите описание изображения здесь

Ответ №1:

Если у вас такая же проблема, это, вероятно, не лучшее решение, но оно работает. Просто измените useEffect, который распространяется на isFocused hook, на это:

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