如何仅在第一次使用时显示屏幕?

How to show a screen only on first time use?

我试图只显示一次许可协议屏幕。在该屏幕上,有一个 ACCEPT 按钮,单击后 - 它会将值保存到 AsyncStorage

在 app.js 中,然后我在 AsyncStorage 中检查该键的值并采取相应的行动。 我的问题是,当我希望许可协议显示时,登录屏幕总是先显示。

我认为这是一个异步问题,但不确定如何解决它。

我确实尝试在 useState 中最初将 loading 设置为 true,并且此方法有效。 但是一旦我第一次接受协议然后重新加载应用程序 - 我会在重定向到登录屏幕之前快速看到许可协议屏幕一秒钟 - 不太理想。

控制台日志按预期打印值,但我认为导航在 useEffect 逻辑完成之前呈现。

App.js

function App() {


const [loading, setLoading] = useState(false);

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

  const load = async () => {
    await AsyncStorage.getItem('isAgreementAccepted').then(result => {
      console.log('RES: ', result)
        if (result == null) {
           setLoading(true);

        } else {
           setLoading(false);
        }
    })

}

  return (
    <NavigationContainer>
      <Stack.Navigator> 
         {loading && <Stack.Screen
          name="EndUserAgreement"
          component={EndUserAgreementScreen}
          options={{ headerShown: false }}
        />}
         <Stack.Screen
          name="Login"
          component={LoginScreen}
          options={{ headerShown: false }}
        />

您需要做的是在 Stack.Navigator.

内正常渲染屏幕

并且一旦你得到一个正值就知道这是用户第一次打开应用程序,你必须正常导航到那个屏幕,如下代码所示:

import { useNavigation } from '@react-navigation/native';

function App() {


  const [loading, setLoading] = useState(false);
  const navigation = useNavigation();

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

  const load = async () => {
    await AsyncStorage.getItem('isAgreementAccepted').then(result => {
      console.log('RES: ', result)
        if (result == null) {
            navigation.navigate('EndUserAgreement');
            await setLocalStoreData('isAgreementAccepted', 'true');
        }
    });
  }

  return (
    <NavigationContainer>
      <Stack.Navigator> 
         <Stack.Screen
          name="EndUserAgreement"
          component={EndUserAgreementScreen}
          options={{ headerShown: false }}
        />
         <Stack.Screen
          name="Login"
          component={LoginScreen}
          options={{ headerShown: false }}
        />

就像你说的,你 Stack.screens 在设置加载状态之前渲染,所以你是登录屏幕自己加载,然后一旦加载设置为 true 你的 endUserAgreement 屏幕正在加载- 但您的导航 (react-navigation?) 不会自动切换您的路线

您可以:

  • 使用 useNavigation hook & .navigate() 导航到 endUserAgreement 屏幕(在这种情况下呈现两个 Stack.screen,并在 Stack.Navigator 上设置 initialRouteName至 'login')

  • 如果存储调用 returns null,则只保留 endUserAgreement 屏幕,这将强制导航仅显示该屏幕 - 类似于:

{loading ? (
  <Stack.Screen
    name="EndUserAgreement"
    component={EndUserAgreementScreen}
    options={{ headerShown: false }}
  />
) : ( 
  <Stack.Screen
    name="Login"
    component={LoginScreen}
    options={{ headerShown: false }}
  />
  {/* ... other screens here */}
)}
  • 在存储调用完成之前显示加载屏幕,然后根据其结果设置 initialRouteName:
const [loading, setLoading] = useState(null)

const load = async () => {
    await AsyncStorage.getItem('isAgreementAccepted').then(result => {
      console.log('RES: ', result)
        if (result == null) {
           setLoading(true);
        } else {
           setLoading(false);
        }
    })

}

  return (
    <NavigationContainer>
       
      {loading === null ? (
        <LoadingScreen />
      ) : (
        <Stack.Navigator initialRouteName={loading ? 'EndUserAgreement' : 'login'}>
         <Stack.Screen
          name="EndUserAgreement"
          component={EndUserAgreementScreen}
          options={{ headerShown: false }}
        />}
         <Stack.Screen
          name="Login"
          component={LoginScreen}
          options={{ headerShown: false }}
        />

所以我们默认为 null 加载状态,显示加载组件,直到它被设置为 true 或 false,然后将初始路由名称设置为正确的屏幕名称。