Home > OS >  Best practice for logging out of React Native app?
Best practice for logging out of React Native app?

Time:11-11

I have currently implemented the sign out functionality on my app with (using firebase authentication):

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

However, I understand this isn't enough as I notice that some state is being preserved accross users (state is preserved even after logout), and I was wondering what the best way to clear/reset all the state is.

Do I need to manually unmount all my components (I still don't quite understand how/when component unmounting happens), or is there an easy way I can achieve this using navigation or context tools?

I am using the Context API and 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>
  );
};

CodePudding user response:

It's hard to say because a lot of this is application specific, but generally speaking, you need to dedicate a single method which is capable destroying a user's session, and making sure that's persistent. Maybe it's logging out of Firebase, maybe it's clearing some cookies, maybe it's updating some other persistent state.

The point is, you write a single method which is responsible for performing all of the data actions to make sure that session doesn't exist any more. Importantly, it's not associated with any navigation or whatever. It's just the pure data operations.

Then you have this reusable function to log the user out that can be called from wherever. Applied to your example...

// 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"));

Finally in terms of the UI, it would probably make sense to move the user first. Otherwise the user would see their state disappear from the screen before their eyes!

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