下面我将展示如何在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))}
>