- ReactJS Tutorial
- ReactJS - Home
- ReactJS - Introduction
- ReactJS - Installation
- ReactJS - Features
- ReactJS - Advantages & Disadvantages
- ReactJS - Architecture
- ReactJS - Creating a React Application
- ReactJS - JSX
- ReactJS - Components
- ReactJS - Nested Components
- ReactJS - Using Newly Created Components
- ReactJS - Component Collection
- ReactJS - Styling
- ReactJS - Properties (props)
- ReactJS - Creating Components using Properties
- ReactJS - props Validation
- ReactJS - Constructor
- ReactJS - Component Life Cycle
- ReactJS - Event management
- ReactJS - Creating an Event−Aware Component
- ReactJS - Introduce Events in Expense Manager APP
- ReactJS - State Management
- ReactJS - State Management API
- ReactJS - Stateless Component
- ReactJS - State Management Using React Hooks
- ReactJS - Component Life Cycle Using React Hooks
- ReactJS - Layout Component
- ReactJS - Pagination
- ReactJS - Material UI
- ReactJS - Http client programming
- ReactJS - Form Programming
- ReactJS - Controlled Component
- ReactJS - Uncontrolled Component
- ReactJS - Formik
- ReactJS - Conditional Rendering
- ReactJS - Lists
- ReactJS - Keys
- ReactJS - Routing
- ReactJS - Redux
- ReactJS - Animation
- ReactJS - Bootstrap
- ReactJS - Map
- ReactJS - Table
- ReactJS - Managing State Using Flux
- ReactJS - Testing
- ReactJS - CLI Commands
- ReactJS - Building and Deployment
- ReactJS - Example
- Hooks
- ReactJS - Introduction to Hooks
- ReactJS - Using useState
- ReactJS - Using useEffect
- ReactJS - Using useContext
- ReactJS - Using useRef
- ReactJS - Using useReducer
- ReactJS - Using useCallback
- ReactJS - Using useMemo
- ReactJS - Custom Hooks
- ReactJS Advanced
- ReactJS - Accessibility
- ReactJS - Code Splitting
- ReactJS - Context
- ReactJS - Error Boundaries
- ReactJS - Forwarding Refs
- ReactJS - Fragments
- ReactJS - Higher Order Components
- ReactJS - Integrating With Other Libraries
- ReactJS - Optimizing Performance
- ReactJS - Profiler API
- ReactJS - Portals
- ReactJS - React Without ES6 ECMAScript
- ReactJS - React Without JSX
- ReactJS - Reconciliation
- ReactJS - Refs and the DOM
- ReactJS - Render Props
- ReactJS - Static Type Checking
- ReactJS - Strict Mode
- ReactJS - Web Components
- Additional Concepts
- ReactJS - Date Picker
- ReactJS - Helmet
- ReactJS - Inline Style
- ReactJS - PropTypes
- ReactJS - BrowserRouter
- ReactJS - DOM
- ReactJS - Carousel
- ReactJS - Icons
- ReactJS - Form Components
- ReactJS - Reference API
- ReactJS Useful Resources
- ReactJS - Quick Guide
- ReactJS - Useful Resources
- ReactJS - Discussion
ReactJS - State management
We are going to do below action to manage our redux store.
Fetching the expenses from server through async fetch api and set it in Redux store.
Add new expense to the server through async fetch programming and set add the new expense in the Redux store.
Delete existing expense from the server through async fetch api and update the Redux store.
Let us create action types, action creator, actions and reducers for managing the Redux state.
Create a folder actions under src folder.
Next, create a file, types.js to create action types.
export const LIST_EXPENSE_STARTED = 'LIST_EXPENSE_STARTED'; export const LIST_EXPENSE_SUCCESS = 'LIST_EXPENSE_SUCCESS'; export const LIST_EXPENSE_FAILURE = 'LIST_EXPENSE_FAILURE'; export const ADD_EXPENSE_STARTED = 'ADD_EXPENSE_STARTED'; export const ADD_EXPENSE_SUCCESS = 'ADD_EXPENSE_SUCCESS'; export const ADD_EXPENSE_FAILURE = 'ADD_EXPENSE_FAILURE'; export const DELETE_EXPENSE_STARTED = 'DELETE_EXPENSE_STARTED'; export const DELETE_EXPENSE_SUCCESS = 'DELETE_EXPENSE_SUCCESS'; export const DELETE_EXPENSE_FAILURE = 'DELETE_EXPENSE_FAILURE';
Next, create a file, index.js under actions folder to create action creators.
import { LIST_EXPENSE_STARTED, LIST_EXPENSE_SUCCESS, LIST_EXPENSE_FAILURE, ADD_EXPENSE_STARTED, ADD_EXPENSE_SUCCESS, ADD_EXPENSE_FAILURE, DELETE_EXPENSE_STARTED, DELETE_EXPENSE_SUCCESS, DELETE_EXPENSE_FAILURE, } from "./types"; export const getExpenseListStarted = () => { return { type: LIST_EXPENSE_STARTED } } export const getExpenseListSuccess = data => { return { type: LIST_EXPENSE_SUCCESS, payload: { data } } } export const getExpenseListFailure = error => { return { type: LIST_EXPENSE_FAILURE, payload: { error } } } export const addExpenseStarted = () => { return { type: ADD_EXPENSE_STARTED } } export const addExpenseSuccess = data => { return { type: ADD_EXPENSE_SUCCESS, payload: { data } } } export const addExpenseFailure = error => { return { type: ADD_EXPENSE_FAILURE, payload: { error } } } export const deleteExpenseStarted = () => { return { type: DELETE_EXPENSE_STARTED } } export const deleteExpenseSuccess = data => { return { type: DELETE_EXPENSE_SUCCESS, payload: { data } } } export const deleteExpenseFailure = error => { return { type: DELETE_EXPENSE_FAILURE, payload: { error } } }
Here, we created one action creator for every possible outcome (success, failure and error) of fetch api. Since we are going to use three web api calls and each call will have three possible outcomes, we use 9 action creators.
Next, create a file, expenseActions.js under actions folder and create three functions to fetch, add and delete expenses and to dispatch state changes.
import { getExpenseListStarted, getExpenseListSuccess, getExpenseListFailure, addExpenseStarted, addExpenseSuccess, addExpenseFailure, deleteExpenseStarted, deleteExpenseSuccess, deleteExpenseFailure } from "./index"; export const getExpenseList = () => async dispatch => { dispatch(getExpenseListStarted()); try { const res = await fetch('http://localhost:8000/api/expenses'); const data = await res.json(); var items = []; data.forEach((item) => { let newItem = { id: item._id, name: item.name, amount: item.amount, spendDate: item.spend_date, category: item.category } items.push(newItem) }); dispatch(getExpenseListSuccess(items)); } catch (err) { dispatch(getExpenseListFailure(err.message)); } } export const addExpense = (data) => async dispatch => { dispatch(addExpenseStarted()); let newItem = { name: data.name, amount: data.amount, spend_date: data.spendDate, category: data.category } console.log(newItem); try { const res = await fetch('http://localhost:8000/api/expense', { method: 'POST', body: JSON.stringify(newItem), headers: { "Content-type": "application/json; charset=UTF-8" } }); const data = await res.json(); newItem.id = data._id; dispatch(addExpenseSuccess(newItem)); } catch (err) { console.log(err); dispatch(addExpenseFailure(err.message)); } } export const deleteExpense = (id) => async dispatch => { dispatch(deleteExpenseStarted()); try { const res = await fetch('http://localhost:8000/api/expense/' + id, { method: 'DELETE' }); const data = await res.json(); dispatch(deleteExpenseSuccess(id)); } catch (err) { dispatch(deleteExpenseFailure(err.message)); } }
Here,
Used async fetch api to do web api calls.
Used dispatch function to dispatch proper action during success, failure and error events.
Create a folder, reducers under src folder and create a file, index.js under reducers folder to create Redux reducers.
import { LIST_EXPENSE_STARTED, LIST_EXPENSE_SUCCESS, LIST_EXPENSE_FAILURE, ADD_EXPENSE_STARTED, ADD_EXPENSE_SUCCESS, ADD_EXPENSE_FAILURE, DELETE_EXPENSE_STARTED, DELETE_EXPENSE_SUCCESS, DELETE_EXPENSE_FAILURE } from "../actions/types"; // define initial state of user const initialState = { data: null, loading: false, error: null } export default function expenseReducer(state = initialState, action) { switch (action.type) { case LIST_EXPENSE_STARTED: return { ...state, loading: true } case LIST_EXPENSE_SUCCESS: const { data } = action.payload; return { ...state, data, loading: false } case LIST_EXPENSE_FAILURE: const { error } = action.payload; return { ...state, error } case ADD_EXPENSE_STARTED: return { ...state, loading: true } case ADD_EXPENSE_SUCCESS: return { ...state, loading: false } case ADD_EXPENSE_FAILURE: const { expenseError } = action.payload; return { ...state, expenseError } case DELETE_EXPENSE_STARTED: return { ...state, loading: true } case DELETE_EXPENSE_SUCCESS: return { ...state, data: state.data.filter(expense => expense.id !== action.payload.data), loading: false } case DELETE_EXPENSE_FAILURE: const { deleteError } = action.payload; return { ...state, deleteError } default: return state } }
Here, we have updated the redux store state for each action type.
Next, open index.js file under src folder and include Provider component so that all the components can connect and work with the redux store.
import React from 'react'; import ReactDOM from 'react-dom'; import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import { Provider } from 'react-redux'; import rootReducer from './reducers'; import App from './components/App'; const store = createStore(rootReducer, applyMiddleware(thunk)); ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') );
Here,
- Imported createStore and applyMiddleware
- Imported thunk from redux-thunk library (for async fetch api)
- Imported Provider from redux library
- Created newstore using createStore by configuring reducer and thunk middleware
- Attached the Provider component as top level component with redux store
To Continue Learning Please Login
Login with Google