#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])