Advanced React Development

Master advanced React patterns, state management, performance optimization, and testing.

advanced Frontend Frameworks 8 hours

Chapter 2: React State Management with Redux

Chapter 2 of 15

Chapter 2: React State Management with Redux

2.1 Redux Fundamentals

Redux is a predictable state container for JavaScript apps. It helps manage application state in a centralized store.

Core Concepts:

  • Store: Single source of truth for application state
  • Actions: Plain objects describing what happened
  • Reducers: Pure functions that specify how state updates
  • Dispatch: Method to send actions to the store
// Action
const increment = () => ({
    type: 'INCREMENT'
});

const addTodo = (text) => ({
    type: 'ADD_TODO',
    payload: { text, id: Date.now() }
});

// Reducer
function counterReducer(state = { count: 0 }, action) {
    switch (action.type) {
        case 'INCREMENT':
            return { count: state.count + 1 };
        case 'DECREMENT':
            return { count: state.count - 1 };
        default:
            return state;
    }
}

// Store
import { createStore } from 'redux';
const store = createStore(counterReducer);

// Usage
store.dispatch(increment());
console.log(store.getState()); // { count: 1 }

2.2 Redux Toolkit

Redux Toolkit (RTK) is the official, opinionated way to write Redux logic. It simplifies Redux development.

import { createSlice, configureStore } from '@reduxjs/toolkit';

// Create slice
const counterSlice = createSlice({
    name: 'counter',
    initialState: { value: 0 },
    reducers: {
        increment: (state) => {
            state.value += 1; // Immer allows direct mutation
        },
        decrement: (state) => {
            state.value -= 1;
        },
        incrementByAmount: (state, action) => {
            state.value += action.payload;
        }
    }
});

// Export actions
export const { increment, decrement, incrementByAmount } = counterSlice.actions;

// Configure store
const store = configureStore({
    reducer: {
        counter: counterSlice.reducer
    }
});

// Usage in React
import { useSelector, useDispatch } from 'react-redux';

function Counter() {
    const count = useSelector(state => state.counter.value);
    const dispatch = useDispatch();
    
    return (
        <div>
            <span>{count}</span>
            <button onClick={() => dispatch(increment())}>+</button>
        </div>
    );
}

2.3 Async Actions with Redux Thunk

// Async thunk
import { createAsyncThunk } from '@reduxjs/toolkit';

export const fetchUser = createAsyncThunk(
    'users/fetchUser',
    async (userId) => {
        const response = await fetch(`/api/users/${userId}`);
        return response.json();
    }
);

// In slice
const usersSlice = createSlice({
    name: 'users',
    initialState: { user: null, loading: false, error: null },
    extraReducers: (builder) => {
        builder
            .addCase(fetchUser.pending, (state) => {
                state.loading = true;
            })
            .addCase(fetchUser.fulfilled, (state, action) => {
                state.loading = false;
                state.user = action.payload;
            })
            .addCase(fetchUser.rejected, (state, action) => {
                state.loading = false;
                state.error = action.error.message;
            });
    }
});