Redux 入门及实践指南 
1. Redux 介绍 
Redux 是 JavaScript 应用的状态容器,提供可预测的状态管理。它可以帮助你开发出行为稳定可预测的应用,运行于不同的环境(客户端、服务器、原生应用),并且易于测试。
为什么需要 Redux? 
- 集中状态管理:所有的应用状态都存储在一个单一的 store 中
- 可预测性:状态的变化是通过纯函数(reducers)来进行的,确保状态变化的可预测性
- 性能优化:通过浅比较来避免不必要的重渲染
- 开发工具支持:强大的开发工具帮助跟踪状态变化
- 状态持久化:便于实现数据持久化和状态恢复
2. Redux 核心概念 
- Store:存储应用的状态
- Action:描述发生了什么的普通对象
- Reducer:根据 action 更新状态的纯函数
- Dispatch:发送 action 的方法
3. 原生 Redux 使用教程 
让我们通过一个简单的计数器示例来学习 Redux:
3.1 基础示例:计数器 
javascript
// counter.js
const { createStore } = require('redux')
// 1. 定义初始状态
const initialState = {
  count: 0
}
// 2. 创建 reducer
const counterReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return {
        ...state,
        count: state.count + 1
      }
    case 'DECREMENT':
      return {
        ...state,
        count: state.count - 1
      }
    default:
      return state
  }
}
// 3. 创建 store
const store = createStore(counterReducer)
// 4. 订阅状态变化
store.subscribe(() => {
  console.log('当前状态:', store.getState())
})
// 5. 发送 action
store.dispatch({ type: 'INCREMENT' })  // 计数器 +1
store.dispatch({ type: 'INCREMENT' })  // 计数器 +1
store.dispatch({ type: 'DECREMENT' })  // 计数器 -14. React-Redux 的使用 
React-Redux 是 Redux 的官方 React 绑定库,提供了更便捷的 API。
4.1 使用 React-Redux 的计数器示例 
jsx
// App.jsx
import React from 'react'
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import Counter from './Counter'
const initialState = {
  count: 0
}
const counterReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return {
        ...state,
        count: state.count + 1
      }
    case 'DECREMENT':
      return {
        ...state,
        count: state.count - 1
      }
    default:
      return state
  }
}
const store = createStore(counterReducer)
function App() {
  return (
    <Provider store={store}>
      <Counter />
    </Provider>
  )
}
export default Appjsx
// Counter.jsx
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
function Counter() {
  const count = useSelector(state => state.count)
  const dispatch = useDispatch()
  return (
    <div>
      <h1>计数器: {count}</h1>
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>增加</button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>减少</button>
    </div>
  )
}
export default Counter4.2 使用 React-Redux 的异步示例 
jsx
// store.js
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
const initialState = {
  todos: [],
  loading: false,
  error: null
}
// Action Types 和 Action Creators
export const FETCH_TODOS_START = 'FETCH_TODOS_START'
export const FETCH_TODOS_SUCCESS = 'FETCH_TODOS_SUCCESS'
export const FETCH_TODOS_FAILURE = 'FETCH_TODOS_FAILURE'
export const fetchTodosStart = () => ({ type: FETCH_TODOS_START })
export const fetchTodosSuccess = (todos) => ({ type: FETCH_TODOS_SUCCESS, payload: todos })
export const fetchTodosFailure = (error) => ({ type: FETCH_TODOS_FAILURE, payload: error })
// 异步 Action Creator
export const fetchTodos = () => async (dispatch) => {
  dispatch(fetchTodosStart())
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/todos')
    const todos = await response.json()
    dispatch(fetchTodosSuccess(todos))
  } catch (error) {
    dispatch(fetchTodosFailure(error.message))
  }
}
// Reducer
const todosReducer = (state = initialState, action) => {
  switch (action.type) {
    case FETCH_TODOS_START:
      return { ...state, loading: true }
    case FETCH_TODOS_SUCCESS:
      return { ...state, loading: false, todos: action.payload }
    case FETCH_TODOS_FAILURE:
      return { ...state, loading: false, error: action.payload }
    default:
      return state
  }
}
export const store = createStore(todosReducer, applyMiddleware(thunk))jsx
// TodoList.jsx
import React, { useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { fetchTodos } from './store'
function TodoList() {
  const dispatch = useDispatch()
  const { todos, loading, error } = useSelector(state => state)
  useEffect(() => {
    dispatch(fetchTodos())
  }, [dispatch])
  if (loading) return <div>加载中...</div>
  if (error) return <div>错误:{error}</div>
  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>
          {todo.title}
          {todo.completed ? ' ✓' : ''}
        </li>
      ))}
    </ul>
  )
}
export default TodoList5. Redux Toolkit 的使用 
Redux Toolkit 是 Redux 官方推荐的工具集,它简化了 Redux 的使用方式。
5.1 使用 Redux Toolkit 的计数器示例 
jsx
// counterSlice.js
import { createSlice } from '@reduxjs/toolkit'
const counterSlice = createSlice({
  name: 'counter',
  initialState: {
    count: 0
  },
  reducers: {
    increment: (state) => {
      state.count += 1
    },
    decrement: (state) => {
      state.count -= 1
    }
  }
})
export const { increment, decrement } = counterSlice.actions
export default counterSlice.reducerjsx
// store.js
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from './counterSlice'
export const store = configureStore({
  reducer: {
    counter: counterReducer
  }
})jsx
// App.jsx
import React from 'react'
import { Provider } from 'react-redux'
import { store } from './store'
import Counter from './Counter'
function App() {
  return (
    <Provider store={store}>
      <Counter />
    </Provider>
  )
}
export default Appjsx
// Counter.jsx
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { increment, decrement } from './counterSlice'
function Counter() {
  const count = useSelector(state => state.counter.count)
  const dispatch = useDispatch()
  return (
    <div>
      <h1>计数器: {count}</h1>
      <button onClick={() => dispatch(increment())}>增加</button>
      <button onClick={() => dispatch(decrement())}>减少</button>
    </div>
  )
}
export default Counter5.2 使用 Redux Toolkit 的异步示例 
jsx
// todosSlice.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
// 创建异步 thunk
export const fetchTodos = createAsyncThunk(
  'todos/fetchTodos',
  async () => {
    const response = await fetch('https://jsonplaceholder.typicode.com/todos')
    return response.json()
  }
)
const todosSlice = createSlice({
  name: 'todos',
  initialState: {
    todos: [],
    loading: false,
    error: null
  },
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchTodos.pending, (state) => {
        state.loading = true
      })
      .addCase(fetchTodos.fulfilled, (state, action) => {
        state.loading = false
        state.todos = action.payload
      })
      .addCase(fetchTodos.rejected, (state, action) => {
        state.loading = false
        state.error = action.error.message
      })
  }
})
export default todosSlice.reducerjsx
// store.js
import { configureStore } from '@reduxjs/toolkit'
import todosReducer from './todosSlice'
export const store = configureStore({
  reducer: {
    todos: todosReducer
  }
})jsx
// TodoList.jsx
import React, { useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { fetchTodos } from './todosSlice'
function TodoList() {
  const dispatch = useDispatch()
  const { todos, loading, error } = useSelector(state => state.todos)
  useEffect(() => {
    dispatch(fetchTodos())
  }, [dispatch])
  if (loading) return <div>加载中...</div>
  if (error) return <div>错误:{error}</div>
  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>
          {todo.title}
          {todo.completed ? ' ✓' : ''}
        </li>
      ))}
    </ul>
  )
}
export default TodoList5.3 Redux Toolkit 异步操作的优势 
- 简化的异步处理: - 使用 createAsyncThunk自动处理异步操作的三种状态(pending/fulfilled/rejected)
- 不需要手动创建 action types 和 action creators
- 自动处理加载状态和错误状态
 
- 使用 
- 更简洁的代码: - 不需要手动设置 thunk middleware
- 可以在 extraReducers中直接使用 builder 模式处理异步状态
- 可以直接修改状态(Immer 会处理不可变更新)
 
- 更好的类型支持: - TypeScript 支持更好
- 自动推断 action 和 state 类型
 
- 内置错误处理: - 自动捕获和处理错误
- 错误信息会被自动传递到 rejected 状态
 
6. Redux Toolkit 的优势 
- 简化配置:内置了很多有用的默认配置
- 减少样板代码:使用 createSlice 自动生成 action creators 和 action types
- 内置不可变更新逻辑:可以直接修改状态,Redux Toolkit 内部使用 Immer 处理不可变更新
- 默认包含有用的中间件:默认包含 redux-thunk,并启用 Redux DevTools
7. 最佳实践建议 
- 使用 Redux Toolkit:它是官方推荐的方式,可以大大简化开发流程
- 合理组织 State 结构:按照领域模型或功能模块组织状态
- 使用选择器(Selectors):通过选择器访问状态,提高代码复用性和维护性
- 异步操作使用 createAsyncThunk:处理异步操作时,推荐使用 Redux Toolkit 的 createAsyncThunk
- 遵循 Redux 的三大原则: - 单一数据源
- State 是只读的
- 使用纯函数进行修改
 
8. 调试工具 
推荐使用 Redux DevTools 进行调试:
- 安装浏览器扩展(Chrome/Firefox)
- 在开发时可以查看: - Action 历史
- State 变化
- 时间旅行调试
- Action 回放
 
9. 总结 
Redux 的发展经历了从原生 Redux 到 React-Redux,再到 Redux Toolkit 的过程。每一次演进都是为了简化开发流程,减少样板代码。现在推荐直接使用 Redux Toolkit 开发新项目,它提供了最佳的开发体验和工具支持。
记住,虽然 Redux 很强大,但不是所有项目都需要使用它。如果你的应用状态管理较为简单,使用 React 的 Context API 和 useReducer 可能就足够了。在选择状态管理方案时,要根据项目的实际需求来决定。