Skip to content

Instantly share code, notes, and snippets.

@AllGistsEqual
Created April 25, 2021 21:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AllGistsEqual/1e999a6258a579f2685bf227f531e735 to your computer and use it in GitHub Desktop.
Save AllGistsEqual/1e999a6258a579f2685bf227f531e735 to your computer and use it in GitHub Desktop.

SERIES: React Native (Step by Step) - Auth Flow Navigation with Mock User Login

Preparations

For our AuthFlow example, we need a few additional screens. For one we want to allow the user to both sign in (existing users) and sign up (new users) and in addition to the AppLoading screen (for loading / initialising user data) I've added an AppCheck screen where I will, later on, check for version updates in the app stores and such.

I went one step further and split them into AuthStack (sign in/sign up) and InitStack (splash screen, and a screen for the app to check version updates and such). We won't use this immediately but that way we won't have to reshuffle everything later on.

https://gist.github.com/2ad08d24fc2312f27fba0b1a9f032aa2

Here is a list of our old and new screen components, sorted by their stack. You can copy one of the existing screens, I copied the old SplashScreen as it already had the redux code we'll use later. For the AppCheckScreen I simply made a copy of our AppLoadingScreen from before.

Don't worry too much about this, we will address those later, one by one.


In our MainNavigation component, we add the new screens accordingly. The stacks separation I prepared above won't be represented here for now so Splash, AppCheck, SignIn and SignUp are all for the "not logged in" users.

https://gist.github.com/2200b3843188c6a2e89e402d3c5f919d

Skippable Splash Screen

Starting with the SplashScreen, we're building a small mechanism to trigger a navigation event after a few seconds or when the user taps the screen to trigger it manually. This is a common pattern you see in many apps.

Instead of the useEffect hook you are probably familiar with by now, we will be using the useFocusEffect() hook from react navigation because it will "mount" and "unmount" when the screen gains and loses focus. A common pitfall of Navigation stacks is that screens do not "unmount" when you navigate away within the same stack which means that your useEffect() cleanup will not be triggered.

On focus of this screen, we start a timeout and store the timeoutID in a const to use for the clean-up of the running timer when the user taps on the screen to navigate. As recommended by the docs, we are wrapping our code in a useCallback() hook to prevent running the code too often and do the same for the navigate() function that we use for timer and onPress event.

https://gist.github.com/40c98a7f0d067e8503ae1f70dc12e0ad

I had to bump my eslint for hooks from 4.0.0 to 4.0.3 to get rid of a false positive for useFocusEffect as the "Effect" suffix triggered a rule it should not. If you use my code from the last session, you might need to do that too.

Version bumped to this => "eslint-plugin-react-hooks": "^4.0.3"

At this point and to test our new pages and routes, our SignUp and SignIn screens will be mocked placeholders, simply using the redux action to mock a successful login. I've also added a small button to navigate between SignUp and SignIn.

https://gist.github.com/c4fc023bfae94d02c890480852f91099

Mocking the login

I will briefly go over the mock login I'm using. To represent real server/api interaction, I've mocked a promise using a timeout that will return the expected mock values. I'm skipping the types I've used and advise you to simply copy the following file from GitHub as this is only a mock authentification and not the focus of this article. XXXXX
X
X FILL IN GITHUB LINK HERE
X
XXXXX

https://gist.github.com/4725f73e737b464ff763e65d54de23f6

We can now use this to create a simple login and register call. The fake login can be set to fail by supplying an additional boolean as a third parameter (useful for testing) but other than that will expect an email and password and tries to match those to our user array. All in plain text, as you would expect from a first class cheap mock api.

I've added a slight variation in form of a createAccount function as well for the SignUp. The response contains a token that would be saved and used in all following requests to pass as a logged-in user in a real application.

https://gist.github.com/f12a14b4e3f29537ae67d5e17a28ab45

Wiring up Redux and Mock API

We now need to do the real work, setting up the real redux code for users so our previous user.ts duck will now be rewritten completely.

Let's start with our annotations and initial state. The login will be a simple boolean, just as before but additionally we will keep track of the login state to make a differentiation between not logged in, logged out and failed to log in as well as loading during the login.

Also, we will store the user email, a message text and a flag to mark newly registered users. This way we can display login errors from our api or a message for a user that successfully logged out and perform additional things for new users that might not have been fully set up yet, depending on the app you are planning to build.

https://gist.github.com/1d665ebe7959dc4248cad3e14f94cad4

Actions

We will use the setLogin action to store a logged-in user's info in our state. This action will no longer be called directly from the app. Instead, we will use if in the userMiddleware we are about to write.

The new setLogout action will contain the new loginState and message, again mainly to be used within our middleware.

https://gist.github.com/f14d0d7d5de375b019474fe8d76ff130

When the user tries to log in or sign up, he will only enter an email and password. We will do the rest in our middleware and reducer.

https://gist.github.com/299b3dc348a9f66fc57556eb0f3dbae1

Selectors

For easier access, we will set up a total of 3 selectors for different parts of our state to be used in the frontend. We know selectLogin already. Additionally, we now have a flag for isSubmitting during the api request and the loginMessage, to update the UI accordingly and provide useful feedback for user interactions.

https://gist.github.com/8c1ecd23a04acc51025bb2ab89d4a1b4

Middleware

In our middleware, we will listen to login and signup attempts, call our mock code and dispatch additional actions according to the results from the mock api.

As you see, we simply dispatch the setLogout action to pass on the new loginState and error message.

https://gist.github.com/9d2da1da9ec29354690790e2e496b4ce

Reducer

The last bit is our Reducer code. This is where it all comes together. When the user attempts to log in, we update state and message to reflect this in the UI and then wait for updates via setLogin and setLogout.

https://gist.github.com/0ce221e3970cf3d4fadb73b8f926268d

A proper login form

On our SignIn and SignUp screens, we can now replace the mock button with a propper login form from a separate component file.

https://gist.github.com/0c0dcf35cf3567fbecfb6ea16504017c

Aaaaand we're done.

Next time we will look at nested navigations and other navigation patterns. Until then I hope you enjoyed this lesson and were able to abstract this pattern for your own projects.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment