React Native -检测应用首次启动

gjmwrych  于 2023-05-18  发布在  React
关注(0)|答案(2)|浏览(275)

我正在为我的react原生应用程序使用React navigation v6。我一直在试图检测应用程序是否是用户第一次启动的。
我尝试通过AsyncStorage设置FIRST_LAUNCH,然后根据它的值,我在Stack.Navigator中设置initialRouteName。这似乎不起作用,因为我开始知道createNativeStackNavigator是同步的,并不等待getItem的承诺被履行或拒绝来完成执行。
App.js

const App = () => {
    useEffect(() => {
        SplashScreen.hide();
    },[]);
    return (
        <View style={styles.container}>
            <Routes />
        </View>
    );
};

Routes.js

const Stack = createNativeStackNavigator();

function Routes(){
    const [firstLaunch , setFirstLaunch] = useState(true);
    
    const checkFirstLaunch = () => {
        AsyncStorage.getItem('FIRST_LAUNCH').then(value => {
            if(value === null){
                AsyncStorage.setItem('FIRST_LAUNCH', 'false');
            }
            setFirstLaunch(false);
        })
    }

    useEffect(() => {
        checkFirstLaunch();
        
    }, [])

    return(
        <NavigationContainer>
                <Stack.Navigator
                    screenOptions={{
                        headerShown: false
                    }}
                    initialRouteName={firstLaunch ? 'Onboarding' : 'TenantHome'}
                >
                    <Stack.Screen name="Onboarding" component={OnboardingRoutes} />
                    <Stack.Screen name="TenantHome" component={TenantRoutes} />
                </Stack.Navigator>
        </NavigationContainer>
    )
}

export default Routes;

这似乎不起作用,firstLaunch总是正确的。
我也读过一个解决方案,有人建议我自己制作一个闪屏,这是默认的第一个屏幕,并使用它来相应地导航到入职或租户主屏幕。但是我已经有了一个由LaunchScreen.xib设置的闪屏,并在App.js中使用SplashScreen.hide()隐藏它。我也不知道手动创建它是否是一种好的做法。
有人能帮我解决这个问题吗?

s4chpxco

s4chpxco1#

也许你应该像这样尝试async/await:

const controlStorage = async () => {
  if (await !AsyncStorage.getItem("FIRST_LAUNCH")) {
    AsyncStorage.setItem('FIRST_LAUNCH', 'false');
  }
  setFirstLaunch(false);
}

或者:

const controlStorage = async () => {
  await AsyncStorage.getItem("FIRST_LAUNCH")) ? setFirstLaunch(false); : AsyncStorage.setItem('FIRST_LAUNCH', 'false'); setFirstLaunch(false);
}

异步存储的工作方式与localStorage不同。这就是为什么有时候我们会有点困惑。我们从asyncstorage得到不同的数据

5sxhfpxr

5sxhfpxr2#

如果你想使用AsyncStorage,那么下面的代码应该可以正常工作:

const checkFirstLaunch = async () => {
    const __first_launch = await AsyncStorage.getItem('FIRST_LAUNCH');
    if (!__first_launch) {//This means that no key found with name 'FIRST_LAUNCH' which indicates that the app is launched for the first time
        AsyncStorage.setItem('FIRST_LAUNCH', "Done");//Instead of false try setting value to something like "Done"
        setFirstLaunch(true);//This line is unneccesary as you are setting the default value to true
    } else {//This means that that app is not launched for the first time so we can set setFirstLaunch to false
        setFirstLaunch(false);
    }
}

如果上面的代码仍然不起作用,那么你可以尝试使用react-native-sqlite-storage。我知道它会增加代码的复杂性,但它比AsyncStorage快得多,所以它也会提高应用的性能。
检查下面的代码以供参考:

import { openDatabase } from 'react-native-sqlite-storage';
var db = openDatabase({ name: 'YOURAPPDB.db' });

useEffect(() => {
    CreateFirstLaunchTable();//Always remember to create the table first before accessing it
    CheckFirstLaunch();//Checking First Launch in local db
}, []);

const CreateFirstLaunchTable = () => {
    try {
        db.transaction(tx => {
            tx.executeSql(
                'CREATE TABLE IF NOT EXISTS FirstLaunch (ID INTEGER PRIMARY KEY AUTOINCREMENT, IsFirstLaunch TEXT)'
                , null, (txObj, resultSet) => {
                    console.log('CreateFirstLaunchTable', resultSet);
                }, (txObj, error) => {
                    console.log('FirstLaunch Table Creation Error : ', txObj.message);
                }
            );
        })
    }
    catch (ex) {
        console.log('Table Creation Error: ' + ex);
    }
}

const InsertDataIntoFirstLaunch = () => {
    try {
        db.transaction(tx => {
            tx.executeSql("INSERT INTO FirstLaunch (IsFirstLaunch) values ('Done')", null,
                (txObj, resultSet) => {
                    if (resultSet.rowsAffected == '1') {
                        console.log('Data inserted successfully');
                    }
                    else {
                        console.log('No Data Insert or updated : ', JSON.stringify(txObj), JSON.stringify(resultSet));
                    }
                },
                (txObj, error) => {
                    console.log('Data Insert/Update Error : ', txObj.message);
                }
            )
        })
    }
    catch (e) {
        console.log(e);
    }
}

const CheckFirstLaunch = () => {
    try {
        db.transaction(function (txn) {
            txn.executeSql(
                "SELECT * FROM FirstLaunch", null,
                (txObj, resultSet) => {
                    if (resultSet.rows.length == 0) {//It means there is no data in the table which indicates that the app is launched for the first time
                        setFirstLaunch(true);
                    }
                    else {//resultSet.rows.length will always be 1 after 2nd and subsequent launches
                        setFirstLaunch(false);
                        InsertDataIntoFirstLaunch();//Inserting into local db
                    }
                },
                (txObj, error) => {
                    console.log('Getting table details error : ', txObj.message);
                }
            );
        });
    }
    catch (e) {
        console.log(e);
    }
}

相关问题