首页 > 解决方案 > 如何在 React Native 中使用来自 AsyncStorage 的值触发条件渲染?

问题描述

我正在使用 React Native 来构建一个应用程序,但我正在为条件渲染而苦苦挣扎。我想要一个教程屏幕,仅在用户第一次打开应用程序时显示。在那之后,它不应该再显示了。在教程中,有一个“开始”按钮应该触发进入应用程序。按下按钮会在 AsyncStorage“showTutorial”中保存为 false,因此下次它不会显示。但是,按下按钮不会隐藏教程并转到主应用程序,只有当我重新打开应用程序、保存文件(在 VSCode 中工作)或重新加载应用程序时,它才会刷新并且不再显示教程页面。我不明白为什么这不起作用,特别是为什么状态变量没有改变并触发另一个屏幕。

当按下按钮时,本地存储会根据日志使用正确的值进行更新。

那么如何实现按下按钮后直接进入主应用程序呢?

应用导航.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>
);

教程.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>
);

PS 仅在 Android 模拟器和物理设备上测试。

标签: react-native

解决方案


我看到的问题是您没有使用 async/await 来调用getShowTutorial. useEffect结果,app-navigation.js 中的组件在AsyncStorage可以检索到值之前呈现。本文解释了在useEffect. https://javascript.plainenglish.io/how-to-use-async-function-in-react-hook-useeffect-typescript-js-6204a788a435

尝试这样的事情:

useEffect(() => {
  (
    async function () {
      await getShowTutorial()
    }
  )()
}, [])

另外,尝试将 await/async 与onPress处理程序一起使用:

onPress={async () => {await saveData('showTutorial', false)}}

让我知道这是否有帮助!


推荐阅读