Redux in React

What is redux?
Redux is for managing and centralizing application state.
Core components of redux
  1. Action:
    • Actions are the payloads of information that send data from your application to your store.
      They are the only source of information for the store.
      It means any state change necessary, the change request would be dispatched through the actions.
  2. Reducer:
    • Actions describe the fact that something happened, but they don’t specify how the application’s state changes in response.
      When an action is dispatched for a state change, it’s the reducer's duty to make changes to state and return the new state.
  3. View:
    • This is where the UI of the application is kept.
  4. Store:
    • With the help of reducers, a store can be created which holds the entire state of the application.
      It is recommended to use a single store.
  5. Middleware:
    • Middleware can be used for a variety of things, including asynchronous API calls.
The typical Redux flow is:
  • UI triggers an Action
  • Action is sent to the Reducer
  • Reducer updates the store
  • State defines the UI

Actions in Redux

Actions in Redux
Models means object strcuture data type.
Models:
                   
                    // Create models using typesrcipt
                    // User SignIn
                    // Food Model
                    export interface FoodModel {
                      _id: string;
                      name: string;
                      description: string;
                      category: string;
                      price: number;
                      readyTime: number;
                      images: [string];
                      unit: number;
                    }
                    export interface UserLogin {
                      email: string;
                      password: string;
                    }
                    // User SignUp
                    export interface UserSignUp {
                      email: string;
                      phone: string;
                      password: string;
                    }
                    // User Model
                    export interface UserModel {
                      firstName: string;
                      lastName: string;
                      contactNumber: string;
                      token: string;
                      verified: boolean;
                    }
                   
                   
                
Actions:
                   
                    // Actions 
                    export const onUserLogin = (userData: UserLogin) => {
                      return async (dispatch: Dispatch) => {
                        try {
                          const res = await axios.post(`${BASE_URL}user/login`, {
                            userData,
                          });
                          console.log(res);
                          if (!res) {
                            dispatch({
                              type: 'ON_USER_ERROR',
                              payload: 'Login Error',
                            });
                          } else {
                            dispatch({
                              type: 'ON_USER_LOGIN',
                              payload: res.data,
                            });
                          }
                        } catch (error) {
                          dispatch({
                            type: 'ON_USER_ERROR',
                            payload: 'Login Error',
                          });
                        }
                      };
                    };
                   
                

InitialState in Redux

InitialState in Redux
                   
                    import { UserModel, UserState, FoodModel, UserAction } from '../models'
                    const initialState: UserState = {
                      user: {} as UserModel,
                      location: {} as Location,
                      error: {} as string | undefined,
                      Cart: {} as [FoodModel],
                    };
                   
                

Reducers in Redux

Reducer for user
                   
                      import { UserModel, UserState, FoodModel, UserAction } from '../models'
                      const initialState: UserState = {
                        user: {} as UserModel,
                        location: {} as Location,
                        error: {} as string | undefined,
                        Cart: {} as [FoodModel],
                      };
                      const UserReducer = (state: UserState = initialState, action: UserAction) => {
                        const { type, payload } = action;
                        switch (action.type) {
                          case 'ON_UPDATE_LOCATION':
                            return {
                              ...state,
                              location: payload,
                            };
                          case 'ON_UPDATE_CART':
                            if (!Array.isArray(state.Cart)) {
                              return {
                                ...state,
                                Cart: [payload],
                              };
                            }
                            const exisitngFoods = state.Cart.filter(
                              (item) => item._id == action.payload._id
                            );

                            //Check for Existing Product to update unit
                            if (exisitngFoods.length > 0) {
                              let updateCart = state.Cart.map((food) => {
                                if (food._id === action.payload._id) {
                                  food.unit = action.payload.unit;
                                }
                                return food;
                              });

                              return {
                                ...state,
                                Cart: updateCart.filter((item) => item.unit > 0),
                              };
                            } else {
                              return {
                                ...state,
                                Cart: [...state.Cart, action.payload],
                              };
                            }
                          case 'ON_USER_LOGIN':
                            return {
                              ...state,
                              user: action.payload,
                            };
                          case 'ON_USER_SIGNUP':
                            return {
                              ...state,
                              user: action.payload,
                            };

                          default:
                            return state;
                        }
                     };

                    export { UserReducer };
                   
                

Combine Reducer and Store in Redux

Combine All Reducer in Redux
Combine all reducers in a single reducer.
                   
                    import { combineReducers } from 'redux'
                    import { CartReducer } from './CartReducer'
                    import { UserReducer } from './userReducer'

                    const rootReducer = combineReducers({
                      userReducer: UserReducer,
                      cartReducer: CartReducer,
                    });

                    export type ApplicationState = ReturnType<typeof rootReducer>;
                    export { rootReducer };
                   
                
Store in Redux
We will pass the root reducer in store.
                   
                    import { applyMiddleware, createStore } from 'redux';
                    import { thunk } from 'redux-thunk';
                    import { rootReducer } from './reducers';

                    const store = createStore(rootReducer, applyMiddleware(thunk));
                    export { store };
                   
                

Provider in Redux

Provider in Redux
We will use redux provider to wrap our main NavigationContainer component and pass store in provider.
                   
                      import 'react-native-gesture-handler';
                      import React from 'react';
                      import { NavigationContainer } from '@react-navigation/native';
                      import { RouteNavigation } from 'navigation';
                      import { Provider } from 'react-redux';
                      import { store } from './src/reduxStore';

                      export default function App() {
                        return (
                          <Provider store={store}>
                            <NavigationContainer>
                              <RouteNavigation />
                            </NavigationContainer>
                          </Provider>
                        );
                      }
                   
                

Middleware in Redux

Middleware in Redux
Redux Middleware allows you to intercept (stop/catch) every action sent to the reducer so you can make changes to the action or cancel the action.
Middleware helps us with logging, reporting errors, making asynchronous requests.
                   
                   const store = createStore(mainReducer, applyMiddleware(Thunk));
                   
                

MapStateToProps in React Redux

How to use props in react
React components accept the data from outside via props. The function to get the data out of the store and we can pass our own props or to get data out of the store to show it in our component.
                   
                   const mapStateToProps = (state, props) => {
                        return {
                            name: state.name,
                            age: state.age
                        }
                    }
                   
                

MapDispatchToProps in React Redux

How to use state in react
React components accept the data from outside via props. mapDispatchToProps allows components to dispatch actions to update that state. It takes the entire state as an argument, but it returns an object with functions: Function to update state in Redux store.
                   
                   const mapDispatchToProps = (dispatch) => {
                        return {
                            fetchData: () => dispatch(fetchData())
                        }
                    }
                    export default connect(mapStateToProps, mapDispatchToProps)(UserComponent);
                   
                

Connect in React Redux

Connect
The connect function connects a React component to a Redux store to dispatch the actions.
                   
                   export default connect(mapStateToProps, mapDispatchToProps)(UserComponent);