Building an Authentication Flow with React Navigation
Updated: March 27, 2017
I’m asked fairly often about setting up an authentication flow with React Navigation. That’s what we’ll cover today — we’ll have two “layouts” a signed in layout with a TabNavigator and a signed out layout with a two screen StackNavigator.
I’ll be using React Native Elements to handle the UI for this app.
Our app is going to work like so…
When the user first opens the app we’ll show them the
SignedOut layout where they can then log in (logging in will simply consist of pressing the login button, everything else will just be for looks). When logged in the
SignedIn layout should replace the
SignedOut layout. A user shouldn't be able to swipe or go back to the previous layout unless they log out.
If a user previously logged in then we should show them the
SignedInlayout immediately when they come back to the app.
Upon logging out the
SignedOut layout should then be visible again. Again, a user shouldn't be able to go back to the
SignedIn layout unless they sign in.
If you want to follow along, or check out the finalized code, you can do so by checking out the project on GitHub. To get started all the screens will be set up already and we’ll focus solely on the routing logic.
Thinking about the app overview we know we need two “layouts”. The
SignedOut layout can be represented by a
SignedIn layout will be represented by a
TabNavigator (you could easily use a
We also need a way to determine which initial layout is shown — we’ll handle that in the primary entry point of the app (app/index.js). To keep track of whether the user has previously signed in or not will be accomplished with
AsyncStorage. When logging in we'll set a key to notate that.
Finally we need a root
SwitchNavigator that we’ll use to change primary layouts.
Setting up the SignedOut Layout
First we’ll set up our SignedOut layout. In
app/router.js create a new
StackNavigator with the
You’ll also want to use this SignedOut component in the app entry point.
SignUp.js to, when pressing the "Sign In" button, navigate to the Sign In screen.
That should leave with something like this
Setting Up the SignedIn Layout
Now let’s set up the TabNavigator for the SignedIn layout.
Then render that from the entry point
Leaving with the the following
Tracking Sign In State
Now that we’ve got our different layouts put together let’s first handle our login logic, which takes place in
app/auth.js. This is purely for demonstration's sake - obviously you would want to hook into a real auth system in reality.
onSignOut functions I'm either writing to or removing from AsyncStorage. In the
isSignedIn function I'm returning a promise and in that promise I check for the existence of the "USER_KEY" - if it exists (meaning we're logged in) I resolve
true from the promise, otherwise I resolve
I created these abstractions to keep all of our login logic in one place.
We can then update the
app/index.js to call and use this information in determining which layout to render.
componentDidMount I make a call to the
isSignedIn function to check whether this user was previously logged in and then update the component state with that information. I also tell my component that we've checked and have gotten a response back from that function.
I then use the component state in my render method to determine what should be rendered. If we’re still waiting for a response from the function I render null so there aren’t any flashes of the wrong layout. The rest is self explanatory.
Since our Sign Up/In and Sign Out buttons are already calling the
onSignUp functions we can test this out. When pressing the button you won't notice anything but if you refresh the app you'll notice the new layout rendered.
Configuring the Root Navigator
We’re going to create a new
SwitchNavigator for our root. However, we’re going to create a function that actually returns the new root navigator and we can change the initial route depending on the signed in state.
You can see that my different “layouts” are the screens of this navigator . The big difference is that I’ve wrapped this in a function and I determine the initial route by the
signedIn argument of the function.
I can then call it from my app entry point like so.
This will give the exact same experience as we had before, just using a navigator.
Now if I update the call to
onSignIn in SignIn.js or SignUp.js to, upon resolving the promise returned, navigate to the
SignedIn layout I get the following interaction.
The code for that looks like this
Likewise we can do the opposite for Profile.js
One thing I want to note about this approach is that you’ve got to be intentional and very aware of an re-renders in the file you call the
createRootNavigator because whenever it's called your nav state will be lost.
How are you handling the authentication flow when using React Navigation?
Curious about my strategies for other common tasks in React Native? Checkout any one of my many React Native courses!