在React项目中实现Redux的完整指南

下面我将展示如何在React项目中完整实现Redux状态管理,包括代码结构、配置和实例组件。

1. 项目结构

bash 复制代码
src/
├── app/
│   ├── store.js          # Redux store配置
├── features/
│   ├── counter/          # 功能模块
│   │   ├── counterSlice.js # Redux slice
│   │   └── Counter.js    # 关联组件
├── index.js              # 应用入口
└── App.js                # 根组件

2. 安装依赖

首先确保安装了必要的依赖:

bash 复制代码
npm install @reduxjs/toolkit react-redux

3. 完整代码实现

3.1 创建Redux Store (app/store.js)

javascript 复制代码
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from '../features/counter/counterSlice';
 
export const store = configureStore({
  reducer: {
    counter: counterReducer,
    // 可以添加更多reducer
  },
  // 可选:添加Redux中间件
  middleware: (getDefaultMiddleware) => getDefaultMiddleware(),
  // 可选:启用Redux DevTools扩展
  devTools: process.env.NODE_ENV !== 'production',
});

3.2 创建Slice (features/counter/counterSlice.js)

javascript 复制代码
import { createSlice } from '@reduxjs/toolkit';
 
const initialState = {
  value: 0,
  status: 'idle',
};
 
export const counterSlice = createSlice({
  name: 'counter',
  initialState,
  reducers: {
    increment: (state) => {
      state.value += 1;
    },
    decrement: (state) => {
      state.value -= 1;
    },
    incrementByAmount: (state, action) => {
      state.value += action.payload;
    },
    setStatus: (state, action) => {
      state.status = action.payload;
    },
  },
  // 可选:处理异步逻辑的extraReducers
  extraReducers: (builder) => {
    // 可以在这里添加对异步thunk的响应
  },
});
 
// 导出actions
export const { increment, decrement, incrementByAmount, setStatus } = counterSlice.actions;
 
// 导出reducer
export default counterSlice.reducer;
 
// 可选:创建selector函数
export const selectCount = (state) => state.counter.value;
export const selectStatus = (state) => state.counter.status;

3.3 创建关联组件 (features/counter/Counter.js)

javascript 复制代码
import React, { useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import {
  selectCount,
  selectStatus,
  increment,
  decrement,
  incrementByAmount,
  setStatus,
} from './counterSlice';
 
export function Counter() {
  const count = useSelector(selectCount);
  const status = useSelector(selectStatus);
  const dispatch = useDispatch();
  const [incrementAmount, setIncrementAmount] = useState('2');
 
  return (
    <div>
      <div>
        <button
          aria-label="Increment value"
          onClick={() => dispatch(increment())}
        >
          +
        </button>
        <span>{count}</span>
        <button
          aria-label="Decrement value"
          onClick={() => dispatch(decrement())}
        >
          -
        </button>
      </div>
      <div>
        <input
          value={incrementAmount}
          onChange={(e) => setIncrementAmount(e.target.value)}
          type="number"
        />
        <button
          onClick={() =>
            dispatch(incrementByAmount(Number(incrementAmount) || 0))
          }
        >
          Add Amount
        </button>
      </div>
      <div>
        <button onClick={() => dispatch(setStatus('loading'))}>
          Set Status to Loading
        </button>
        <div>Current Status: {status}</div>
      </div>
    </div>
  );
}

3.4 配置应用入口 (index.js)

javascript 复制代码
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import App from './App';
import { store } from './app/store';
import './index.css';
 
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);

3.5 根组件 (App.js)

javascript 复制代码
import React from 'react';
import { Counter } from './features/counter/Counter';
 
function App() {
  return (
    <div className="App">
      <header className="App-header">
        <h1>Redux Toolkit Demo</h1>
      </header>
      <main>
        <Counter />
      </main>
    </div>
  );
}
 
export default App;

4. 高级用法:异步逻辑

如果需要处理异步操作(如API调用),可以使用Redux Toolkit的createAsyncThunk

4.1 修改Slice添加异步逻辑

javascript 复制代码
// 在counterSlice.js中添加
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
 
// 创建异步thunk
export const incrementAsync = createAsyncThunk(
  'counter/fetchCount',
  async (amount) => {
    // 这里可以是API调用
    const response = await new Promise((resolve) =>
      setTimeout(() => resolve({ data: amount }), 500)
    );
    return response.data;
  }
);
 
// 然后在slice中处理异步状态
const counterSlice = createSlice({
  // ...其他配置保持不变
  extraReducers: (builder) => {
    builder
      .addCase(incrementAsync.pending, (state) => {
        state.status = 'loading';
      })
      .addCase(incrementAsync.fulfilled, (state, action) => {
        state.status = 'idle';
        state.value += action.payload;
      })
      .addCase(incrementAsync.rejected, (state) => {
        state.status = 'failed';
      });
  },
});

4.2 在组件中使用

javascript 复制代码
// 在Counter组件中添加
import { incrementAsync } from './counterSlice';
 
// 在组件函数中添加
const dispatch = useDispatch();
 
// 然后可以在按钮点击时使用
<button
  onClick={() => dispatch(incrementAsync(Number(incrementAmount) || 0))}
>
相关推荐
轻语呢喃3 小时前
useRef :掌握 DOM 访问与持久化状态的利器
前端·javascript·react.js
wwy_frontend3 小时前
useState 的 9个常见坑与最佳实践
前端·react.js
egghead263163 小时前
React组件通信
前端·react.js
OLong4 小时前
React Update Queue 源码全链路解析:从 setState 到 DOM 更新
前端·react.js
wwy_frontend6 小时前
不想装 Redux?useContext + useReducer 就够了!
前端·react.js
EndingCoder8 小时前
Next.js 中间件:自定义请求处理
开发语言·前端·javascript·react.js·中间件·全栈·next.js
mit6.8248 小时前
[AI React Web]`意图识别`引擎 | `上下文选择算法` | `url内容抓取` | 截图捕获
前端·人工智能·react.js
赛博切图仔9 小时前
React useMemo 深度指南:原理、误区、实战与 2025 最佳实践
前端·react.js·前端框架
egghead263169 小时前
React常用hooks
前端·react.js