#react-native
Вопрос:
Я использую React Native для создания приложения и борюсь с условным рендерингом. Я хочу, чтобы экран учебника отображался только при первом открытии приложения пользователем. После этого его больше не следует показывать. В учебнике есть кнопка «Начать», которая должна вызвать переход к приложению. Нажатие кнопки сохраняет в AsyncStorage значение «showTutorial» в значение false, поэтому в следующий раз оно не будет отображаться. Однако нажатие кнопки не скрывает учебник и не переходит в главное приложение, только если я снова открою приложение, сохраню файл (работающий в VSCode) или перезагрузлю приложение, затем оно обновится, и страница учебника больше не отображается. Я не понимаю, почему это не работает, в частности, почему переменная состояния не изменяется и не запускает другой экран.
Локальное хранилище обновляется при нажатии кнопки с правильным значением на основе журналов.
Итак, как я могу перейти к основному приложению непосредственно после нажатия кнопки?
app-navigation.js:
const [showTutorial, setShowTutorial] = React.useState(true);
const getShowTutorial = async () => {
try {
const LS_showTutorial = await AsyncStorage.getItem('showTutorial');
if (LS_showTutorial !== null) {
setShowTutorial(JSON.parse(LS_showTutorial));
}
} catch (error) {
console.log('Failed to fetch the data from storage', error);
}
};
React.useEffect(() => {
getShowTutorial();
}, []);
return (
<View style={{ flex: 1 }}>
{ showTutorial ? ( // THIS DOES NOT CHANGE WHEN PRESSING THE BUTTON
<TutorialScreen/>
) : (
<DashboardScreen/>
)}
</View>
);
tutorial.js
const saveData = async (key, value) => {
try {
console.log('Saving local data with ', key, ' and ', JSON.stringify(value));
await AsyncStorage.setItem(key, JSON.stringify(value));
} catch (error) {
console.log('Something went wrong', error);
}
};
return (
<View style={styles.basicContainer}>
<Text style={styles.textTitle}>
Hello world!
</Text>
<Button
onPress={() => {
saveData('showTutorial', false);
}}
>Get started</Button>
</View>
);
P.S. Протестировано только на эмуляторе Android и физическом устройстве.
Ответ №1:
Проблема, которую я вижу, заключается в том, что вы не используете асинхронное/ожидание для вызова getShowTutorial
в useEffect
. В результате компонент в app-navigation.js визуализируется до AsyncStorage
того, как можно будет получить значение in. В этой статье объясняется идея, лежащая в основе ожидания асинхронного кода useEffect
. https://javascript.plainenglish.io/how-to-use-async-function-in-react-hook-useeffect-typescript-js-6204a788a435
Попробуйте что-нибудь вроде этого:
useEffect(() => {
(
async function () {
await getShowTutorial()
}
)()
}, [])
Кроме того, попробуйте использовать ожидание/асинхронность с onPress
обработчиком:
onPress={async () => {await saveData('showTutorial', false)}}
Дайте мне знать, если это поможет!
Комментарии:
1. Я попробовал ваши предложения и не помог. Он работает так же, как и раньше.
2. По этой части:
if (LS_showTutorial !== null) { setShowTutorial(JSON.parse(LS_showTutorial)); }
делаетJSON.parse(LS_showTutorial) === false
и не"false"
делает ? Если вы устанавливаете это в строку, она будет оцениваться как правдивая, что объясняет, почему она не работает3. JSON.parse возвращает логическое
false
значение из строки"false"
. Я дважды проверил, и это действительноfalse
как логическоеsetShowTutorial(JSON.parse(LS_showTutorial))
значение . Проблема не в самой функции, если я перезагружаю приложение или сохраняю файл, эта функция запускается правильно, и страница учебника исчезает. Однако он не входит в функцию, когда я нажимаю кнопку.