React State Management with Redux Guide

react
redux
state management

Core Concepts

  • Store: Holds the state of your application
  • Action: Plain object describing what happened
  • Reducer: Function that returns the next state
  • Dispatch: Method to send actions to the store

Setting up Redux

Install necessary packages:

npm install redux react-redux @reduxjs/toolkit

Creating a Store

import { configureStore } from '@reduxjs/toolkit';
import rootReducer from './reducers';
 
const store = configureStore({
  reducer: rootReducer,
});
 
export default store;

Defining Actions

// Using Redux Toolkit's createAction
import { createAction } from '@reduxjs/toolkit';
 
export const increment = createAction('counter/increment');
export const decrement = createAction('counter/decrement');

Creating Reducers

import { createReducer } from '@reduxjs/toolkit';
import { increment, decrement } from './actions';
 
const initialState = { value: 0 };
 
const counterReducer = createReducer(initialState, (builder) => {
  builder
    .addCase(increment, (state, action) => {
      state.value++;
    })
    .addCase(decrement, (state, action) => {
      state.value--;
    });
});
 
export default counterReducer;

Connecting React to Redux

import React from 'react';
import { Provider } from 'react-redux';
import store from './store';
import App from './App';
 
const Root = () => (
  <Provider store={store}>
    <App />
  </Provider>
);
 
export default Root;

Using Redux in Components

import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement } from './actions';
 
function Counter() {
  const count = useSelector((state) => state.counter.value);
  const dispatch = useDispatch();
 
  return (
    <div>
      <button onClick={() => dispatch(decrement())}>-</button>
      <span>{count}</span>
      <button onClick={() => dispatch(increment())}>+</button>
    </div>
  );
}
 
export default Counter;

Async Actions with Redux Thunk

import { createAsyncThunk } from '@reduxjs/toolkit';
 
export const fetchUserById = createAsyncThunk(
  'users/fetchByIdStatus',
  async (userId, thunkAPI) => {
    const response = await fetch(`https://api.example.com/users/${userId}`);
    return response.json();
  }
);
 
// In your reducer
const usersSlice = createSlice({
  name: 'users',
  initialState: { entities: [], loading: 'idle' },
  reducers: {
    // ...other reducers
  },
  extraReducers: (builder) => {
    builder
      .addCase(fetchUserById.pending, (state, action) => {
        state.loading = 'loading';
      })
      .addCase(fetchUserById.fulfilled, (state, action) => {
        state.entities.push(action.payload);
        state.loading = 'idle';
      });
  },
});

Remember, Redux is just one of many state management solutions for React. For simpler applications, React's built-in useState and useContext hooks might be sufficient.