Redux in PURE React Native
Tags: typescript, javascript, reactnative, silvenleaf
Published: 2022-05-05 15:33:46

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
```bash
npm i redux react-redux @reduxjs/toolkit
```
## 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
```typescript 
/* ----------------------
.       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,
}
```

##### Create Reducer
```typescript
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;
```

### CHAPTER 2: Use store
Import this store that we created on your entry file and use it
```typescript
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>
  );
}
```

### 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. 

```typescript
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;
```

### CHAPTER 4: Map state and action to props
```typescript
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)
```
### 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](https://www.linkedin.com/in/silvenleaf/)

Wanna know more about me? Come here! 
[SilvenLEAF.github.io](https://SilvenLEAF.github.io)