【问题标题】:Best practice for logging out of React Native app?退出 React Native 应用程序的最佳实践?
【发布时间】:2021-11-10 21:18:25
【问题描述】:

我目前已经在我的应用上实现了退出功能(使用 firebase 身份验证):

const handleSignOut = () => {
  signOut(auth)
    .then(() => navigation.navigate("Login"))
    .catch((err) => console.error(err));
};

但是,我知道这还不够,因为我注意到某些状态正在跨用户保留(即使在注销后仍保留状态),我想知道清除/重置所有状态的最佳方法是什么。

我是否需要手动卸载所有组件(我仍然不太了解组件卸载的方式/时间),还是有一种简单的方法可以使用导航或上下文工具来实现此目的?

我正在使用 Context API 和 React Navigation:

const Stack = createStackNavigator();

const Navigation = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator
        headerMode="none"
      >
        <Stack.Screen
          name="Register"
          component={RegisterScreen}
        />
        <Stack.Screen
          name="Login"
          component={LoginScreen}
        />
        <Stack.Screen
          name="Home"
          component={HomeScreen}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

【问题讨论】:

    标签: react-native react-navigation react-context


    【解决方案1】:

    很难说,因为其中很多都是特定于应用程序的,但一般来说,您需要专用一个能够破坏用户会话的方法,并确保它是持久的。也许它正在注销 Firebase,也许它正在清除一些 cookie,也许它正在更新一些其他持久状态。

    关键是,您编写一个方法来负责执行所有数据操作,以确保该会话不再存在。重要的是,它与任何导航或其他内容无关。只是单纯的数据操作。

    然后你有这个可重用的功能来注销用户,可以从任何地方调用。应用于您的示例...

    // Notice that things that can possibly fail are wrapped in dedicated try/catches.
    // You don't want the failure to clear some state prevent your ability to clear others.
    const doSomeBigGlobalSessionLogout = async () => {
      const maybeErrors = [];
      try {
        await firebase.signOut(auth);
      } catch (e) {
        maybeErrors.push(e);
      }
      try {
        await clearSomeOtherPersistentState();
      } catch (e) {
        maybeErrors.push(e);
      }
    
      /* do something with errors */
      // for (error of maybeErrors) { ... }
    
      // Still resolve successfully, because you won't want to lock the user from
      // not being able to sign out.
      return Promise.resolve();
    };
    
    // Here you can trust it will never lock the user out, and will always clear state as best as it can.
    doSomeBigGlobalSessionLogout()
       // You *will* get here.
      .then(() => navigation.navigate("Login"));
    

    最后,在 UI 方面,首先移动用户可能是有意义的。否则用户会看到他们的状态从他们眼前的屏幕上消失!

    Promise.resolve()
      .then(() => navigation.navigate("SomePlaceThatsPretty"));
      .then(doSomeBigGlobalSessionLogout)
      .then(() => navigation.navigate("Login"));
    

    【讨论】:

    • 当我清除一些持久状态时,我是否需要逐个进入我拥有的每个页面/屏幕并将所有状态变量设置为其默认值?因为这看起来很麻烦,而且每次我在项目中添加另一个状态变量时都需要更改它。
    • 您不应该这样做,前提是这些组件可能挂在与经过身份验证的用户相关的任何动态分配的数据上。在示例中,您使用 navigation.navigate("Login") 清除状态,但我建议使用 navigation.reset 以确保已卸载任何先前活动的屏幕。
    • 那么我需要手动清除哪个持久状态?我只需要清除 Context API 中的状态吗?
    猜你喜欢
    • 1970-01-01
    • 2021-03-26
    • 1970-01-01
    • 2016-07-25
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 2018-07-08
    • 2019-10-10
    相关资源
    最近更新 更多