DEV Community

Cover image for Redux in PURE React Native
SilvenLEAF
SilvenLEAF

Posted on • Edited on

Redux in PURE React Native

Let's learn how to integrate Redux with PURE React Native!!

TL;DR

  • [x] Create store (from reducers)
  • [x] Use store (on our lovely app)
  • [x] Create actions
  • [x] Map state to props
  • [x] Map action to props

Tales of Redux: Legends untold

Before we dive in depth, let's learn the main concept with a sweet analogy. Store is a storehouse or a warehouse and it is a really big shed, we can keep rice, corns, maize etc. Reducers are like robots that act to manage this store. They are the caretakers of this place. If we want to retrieve or put or remove some stuff from or to this place they'll help us out. We write some commands in a letter and optionally pass the stuff as well. They will read this letter and get the stuff that we pass and will act accordingly to our letter. This letter is called actions. Now let's say, we write a letter saying, please put these 7 maizes on the store as well. Putting these maizes is the action and the 7 maizes that we passed along with this letter are called payload. Now to remember, state is the stuff we store, action is the letter of command that we dispatch a.k.a send to the bots to act upon. Hope this helps. Now let's get to the fun stuff :)

Install the packages

First let's install all the required packages

npm i redux react-redux @reduxjs/toolkit
Enter fullscreen mode Exit fullscreen mode

CHAPTER 1: Create store

We'll keep everything Redux related in a single folder to keep everything organized. So let's start.

First let's create the store. A store is a collection of reducers, the bots, who manage their own part of the warehouse. Each contain a storage also known as state (or initState) and action handler.

In simple words, reducer is a collection of if statements based on actions performing on initState. Whatever we return from the reducer function (normally based on if statements) becomes the new/updated state of that reducer.

Create Store
/* ----------------------
.       method 1
---------------------- */
import { configureStore } from "@reduxjs/toolkit";

export const store = configureStore({
  reducer: {
    app: appSettingsReducer,
    progress: userProgressReducer,
    user: userProfileReducer,
  }
})

export interface IRootState {
  app: IAppSettingState,
  progress: IUserProgressState,
  user: IUserProfileState,
}




/* ----------------------
.       method 2
---------------------- */
import { combineReducers, createStore } from "redux";

const rootReducer = combineReducers({
  app: appSettingsReducer,
  progress: userProgressReducer,
  user: userProfileReducer,
});

export const store = createStore(rootReducer)

export interface IRootState {
  app: IAppSettingState,
  progress: IUserProgressState,
  user: IUserProfileState,
}
Enter fullscreen mode Exit fullscreen mode
Create Reducer
export interface IAppSettingState {
  themeColor: string,
  isSoundOn: boolean,
  isVibrationOn: boolean,
  isDarkTheme: boolean,
  isTutorialShown: boolean,
}

const initState: IAppSettingState = {
  themeColor: 'red',
  isSoundOn: true,
  isVibrationOn: true,
  isDarkTheme: false,
  isTutorialShown: true,
}

export const appSettingsReducerTypes = {
  updateThemeColor: 'UPDATE_THEME_COLOR',
  updateIsDarkTheme: 'UPDATE_IS_DARK_THEME',
}

interface IAction {
  type: string,
  payload?: any,
}

const appSettingsReducer = (state = initState, action: IAction) => {
  switch (action.type) {
    case appSettingsReducerTypes.updateThemeColor:
      return {
        ...state,
        themeColor: action.payload,
      };

    case appSettingsReducerTypes.updateIsDarkTheme:
      return {
        ...state,
        isDarkTheme: action.payload,
      };
    default:
      return state;
  }
}

export default appSettingsReducer;
Enter fullscreen mode Exit fullscreen mode

CHAPTER 2: Use store

Import this store that we created on your entry file and use it

import React from 'react';

import { Provider } from 'react-redux';
import { store } from './app/store/store';

export default function App() {
  return (
    <Provider store={store}>
      <RootDrawer />
    </Provider>
  );
}
Enter fullscreen mode Exit fullscreen mode

CHAPTER 3: Create actions

Action is nothing but a function that returns an object containing "type" and "payload" properties. Reducers do their if statements on this object. This object is the action for that reducer.

Action functions optionally take payload as an argument and return it in the payload.

import { appSettingsReducerTypes } from "../reducers/appSettingsReducer";

export const updateThemeColor = (color: string)=>{
  return {
    type: appSettingsReducerTypes.updateThemeColor,
    payload: color,
  }
}

export const updateIsDarkTheme = (isDarkTheme: boolean)=>{
  return {
    type: appSettingsReducerTypes.updateIsDarkTheme,
    payload: isDarkTheme,
  }
}

const appSettingsActions = {
  updateThemeColor,
  updateIsDarkTheme,
}

export default appSettingsActions;
Enter fullscreen mode Exit fullscreen mode

CHAPTER 4: Map state and action to props

import React from 'react'

import { NavigationProp } from '@react-navigation/native';
import { connect } from 'react-redux';

import { IRootState } from '../../../store/store';
import { IAppSettingState } from '../../../store/reducers/appSettingsReducer';
import { IUserProgressState } from '../../../store/reducers/userProgressReducer';
import userProgressActions from '../../../store/actions/userProgressAction';

interface propsInterface extends IAppSettingState, IUserProgressState {
  navigation: NavigationProp<any>,

  progress: {
    updateRank: typeof userProgressActions.updateRank,
    updateLevel: typeof userProgressActions.updateLevel,
    updateXP: typeof userProgressActions.updateXP,
  },
}


function ActionScreen(props: propsInterface) {
  return (
    <HomeScreen/>
  );
}

const mapStateToProps = (state: IRootState) => {
  return {
    ...state.app,
    ...state.progress,
  }
}

const mapDispatchToProps = (dispatch: any) => {
  return {
    progress: {
      updateRank: (rank: string) => dispatch(userProgressActions.updateRank(rank)),
      updateLevel: (level: number) => dispatch(userProgressActions.updateLevel(level)),
      updateXP: (xp: number) => dispatch(userProgressActions.updateXP(xp)),
    },
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(ActionScreen)
Enter fullscreen mode Exit fullscreen mode

Chapter 5: Integrating Async Storage

Stay tuned for the VERY NEXT Blog :) It's gonna be a BLAST

What's NEXT?

1. Async Storage with Pure React Native

2. Project with Pure React Native

3. More on App Development

4. How to deploy to playstore

5. Insane stuff with JavaScript/TypeScript

6. Writing Automated Tests for any Server

7. How to create an Android APP with NO XP with Expo

(including apk generating)

Got any doubt?

Drop a comment or Feel free to reach out to me @SilveLEAF on Twitter or Linkedin

Wanna know more about me? Come here!
SilvenLEAF.github.io

Top comments (0)