I’m creating a React Native app in which some actions like adding to favorites require the user to be logged in.
The problem
If a certain action needs authentication, the following flow is executed:
- User tab over the favorite button(Protected action)
- A modal(screen with presentation: "modal") is rendered to allow the user to enter their credentials
- If the user is successfully logged in, the modal is closed and the user is directed to the screen on which it was located(
goBack()
navigation action). - THE PROBLEM: user needs to press again over the favorite button, the idea is, if the user is successfully logged in, the action (add to favorites) is executed immediately without the user having to perform the action again.
NOTE: I can have different protected actions on the same screen
Question
how can I request the user to log in to perform the action and have the action executed automatically after successful login?
execute the protected action only once, only when the user logs in successfully and the modal is closed, if the user is already authenticated the protected action should not be executed again.
Example flow
function FavoriteScreen({ navigation }) {
const { isAuthenticated } = useAuth();
if (isAuthenticated) {
addFavorite(productId);
} else {
navigation.navigate("LoginScreen");
}
}
Things I’ve tried
- Send a callback through the parameters(called
nexAction
) from the protected action screen to the login screen, run the callback after successfully log in, and close the modal, but I’m getting non-serializable warning, and this screen implements deep linking, so I cannot ignore the warning as the documentation suggests.
if (isAuthenticated) {
addFavorite();
} else {
navigation.navigate(NavigationScreens.LoginScreen, {
nextAction: addFavorite,
});
}
- Use the
focus
event to run the protected action after the user is successfully logged in and the modal is closed. This approach has some problems, each time user focuses on the screen and is authenticated, the protected action is going to be run, and there may be more than one protected action on the screen, meaning that they will all be executed when the screen is focused.
useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
if (isAuthenticated) {
addFavorite();
}
});
return unsubscribe;
}, [isAuthenticated, navigation, addFavorite]);
2
Answers
Have you tried an effect?
You can’t send a function on nav params, but you can send data. You can try parroting the data back from the login screen and performing your one time action like this:
I think you’re on the right path with
useEffect
. What about storing the user action when clicking a protected action, and then performing the action and clearing the stored value after the user has logged in?Something like:
const [pendingAction, setPendingAction] = useState();
user clicks addFavorite action, but is not logged in:
setPendingAction({type: 'addFavorite', value: 12});
Then handling the login in the modal, the previous screen will stay mounted and keep its state.
And then calling the pendingAction in the
useEffect
: