Adding redux

Part ɪɪ: React-Native UI│Story 09: Add redux and connect User Sign-in component to redux

GIT : Repo | Feature/Story branch| PR

If you are following the series, in this Part-II - React-Native UI, so far we’ve got the Google Sign-in and routing navigation implemented in our react-native app and added a couple of components for User Sign-in and Home screen.

Our next goal is to save the user details that we get from Google after user signs in, like user’s name, email and profile picture, in an application-wide state so that it’s available to other components of the app. To share data across components, we have few options available in react, like childProps or Context API (available officially in React 16+) or redux.

In our example, we would opt for redux, simply because I feel, for a large-scale application, redux is good option to maintain an application-wide state. It allows you to apply useful middlewares. GraphQL or MobX are also few other good options.

Lets get started:

Adding redux

With react-native app’s root folder as pwd on the terminal, run the command:

  • 📂 Create a folder named redux under src folder.
  • 📂 Under redux, create subfolders - actions, reducers and store

Actions

Action Constants:

📄 Under actions folder, add a file actionTypes.js with below code: 👇

User Sign-In Actions:

  • 📂 Create a folder UserSignIn under src/redux/actions folder.
  • 📄 Add a file UserSignInActions.js under src/redux/actions/UserSignIn folder 👇

Reducer for User Sign-in state:

Next, add a reducer to update the app state related to Google user’s basic profile data for the actions we defined above that would be triggered during the sign-in process. For sign in failure case, we would store failure reason in the store.

  • 📄 Add file UserSignInReducer.js under src/redux/reducers folder 👇

Under src\redux\reducers, add index.js, with below code:

Store:

Next, let’s create our redux store.

Under src\redux\store, add index.js with below code:

Wrapping App within redux Provider:

Update App.js as below wrapping the root component with redux Provider providing it the store we created above:

Connect UserSignIn component to redux

Next, we will update our UserSignIn component to connect to redux to update the User’s Sign-in status and Google user details in our store using the actions we defined in src/redux/actions/UserSignInActions.js

Under src/components/UserSignIn, add a file UserSignInConnected.js, with below code:

👆 above, we connected UserSignIn component to redux. In the component, we are going to use redux dispatch actions that we created for the User Sign-in events to update the GoogleUser and GoogleSignIn store props. With this, we now have the redux dispatch actions, mapped in mapDispatchToProps, available as props in UserSignIn component. So lets refactor UserSignIn component as below:

Above, we did a quite a few changes to UserSignIn component:

  1. (line # 7–10) component’s local state now has only two state variables - isSigninInProgress and checkingSignedInStatus, we got rid of loggedInUser and isUserSignedIn.
    loggedInUser is not needed now because we would now store the logged in user in redux state variable googleUser (this.props.googleUser)
    isUserSignedIn state variable is also not needed now. We were using this state variable to render ‘Logout’ button instead of ‘Sign In’ button if its value is true. However, after we added navigation to our app, user would navigate to ‘Home’ screen and won’t stay on the same sign-in screen, thus ‘Logout’ button is not needed on this component. We would add Logout button later in our AppHeader component.
  2. (line # 29 - 33) : react-navigation’s didFocus event subscription and removing the subscription on componentWillUnmount, its explained in the code comments (line # 22 - 28)
  3. (line # 67 - 85) : in onSignInPress method, after user successfully signs in, we call a local method dispatchOnSignIn (line # 90 - 98), that in turn calls this.props.UserSignIn_onSuccess ( which is mapped to the dispatch action UserSignIn_onSuccess in the connected component UserSignInConnnected)
  4. (line # 103 - 110) : also, if user is already signed in, we call getCurrentUserInfo function on line 114. In this function, we again call dispatchOnSignIn after getting the currently signed in user’s details.
  5. (line # 129) : in signOut, after signing out the user, we call this.props.UserSignIn_logOut which is mapped to dispatch action UserSignIn_logOut.
  6. (line # 180-182) :In showSignInError method, before showing the sign-in error to user, we now also call this.props.UserSignIn_onError, which maps to the dispatch action UserSignIn_onError.

Now, instead of using UserSignIn component as is, we would have to use the UserSignInConnected component in the app. For this, lets update index.js file under src/components folder to export the component from UserSignInConnected instead of UserSignIn 👇

Ok, the UserSignIn component is now connected with redux actions and state. We are now dispatching the required actions from the component on events like successful sign-in, logout or sign-in error. Lets make sure the app is working good after all these changes. We haven’t made any changes to the functionality or UI, so we are expecting any change there, but because we added logger as middleware to redux store, we are expecting the actions triggered to be logged to the chrome console. ( Make sure you have ‘react-native debugger’ opened in chrome. )

Now refresh the app on the simulator (it would have Hot reloaded if you have Hot reloading enabled on simulator’s developer menu ).

👆 note the UserSignIn_onSuccess action getting triggered and logged in the background chrome’s debugger console. And on Android: 👇

(️ it took me to restart the app on Android and chrome Remote Debugger couple of times for Remote debugging to work from Android).

Great! Now that we have the logged-in user’s details available in redux store, let’s build a header component next using this user data from redux to display user’s profile picture in the header along with a log out button.

Prev:Google Sing-in for Android🏠Next:Header Component

--

--