React 18.2中使用Redux 5.0.1
在 React 18 中使用 Redux 5(不使用 Redux Toolkit)需要手动设置 store、reducer、action 等核心概念。以下是具体步骤和示例:
1. 安装必要依赖
首先需要安装 Redux 核心库和 React-Redux 绑定库:
npm install redux@5 react-redux@9
# 或
yarn add redux@5 react-redux@9
2. 创建 Redux Store
创建一个 store,包含 reducer 和初始状态:
store.js
// store.js
import { createStore } from 'redux';// 初始状态
const initialState = {count: 0,todos: []
};// 定义Reducer - 根据不同 action 类型处理状态
function rootReducer(state = initialState, action) {switch (action.type) {case 'INCREMENT':return { ...state, count: state.count + 1 };case 'DECREMENT':return { ...state, count: state.count - 1 };case 'ADD_TODO':return {...state,todos: [...state.todos, action.payload]};default:return state;}
}// 创建 store
const store = createStore(rootReducer);export default store;
actions.js
// actions.js
// Action 创建函数 - 返回 action 对象
export const increment = () => ({type: 'INCREMENT'
});export const decrement = () => ({type: 'DECREMENT'
});export const addTodo = (text) => ({type: 'ADD_TODO',payload: text
});
将 Redux Store 提供给 React 应用,在 React 18 中,通常你会在 index.js
或 main.jsx
中使用 <Provider>
包裹你的根组件(比如 <App />
)。
index.jsx
// index.jsx - React 18 入口文件
import React from 'react';
import { createRoot } from 'react-dom/client';
import { Provider } from 'react-redux';
import store from './store';
import App from './App';// React 18 新的渲染方式
const root = createRoot(document.getElementById('root'));
root.render(<Provider store={store}><App /></Provider>
);
在 React 组件中使用 Redux State 和 Dispatch:
App.jsx
// App.jsx
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, addTodo } from './actions';function App() {// 从 store 中获取状态const { count, todos } = useSelector((state) => state);// 获取 dispatch 函数const dispatch = useDispatch();return (<div><h1>Count: {count}</h1><button onClick={() => dispatch(increment())}>+</button><button onClick={() => dispatch(decrement())}>-</button><div><h2>Todos</h2><input type="text" ref={(input) => window.todoInput = input} placeholder="Add todo"/><button onClick={() => {dispatch(addTodo(window.todoInput.value));window.todoInput.value = '';}}>Add</button><ul>{todos.map((todo, index) => (<li key={index}>{todo}</li>))}</ul></div></div>);
}export default App;
假如你有多个reducer,你需要使用 combineReducers:
// src/reducers/index.js
import { combineReducers } from 'redux';
import counterReducer from './counterReducer';const rootReducer = combineReducers({counter: counterReducer,// 其他reducers...
});export default rootReducer;
// counterReducer.js
import { INCREMENT, DECREMENT } from './types';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;}
};export default counterReducer;
核心概念说明
Store:
- 使用 createStore 创建,接收 reducer 作为参数
- 整个应用只有一个 store
Reducer:
- 纯函数,接收 state 和 action 并返回新的状态
- 必须遵循不可变性原则(使用展开运算符 ... 创建新对象)
Action:
- 普通 JavaScript 对象,必须有 type 属性
- 通过 action 创建函数生成,便于复用
在 React 中使用:
- Provider 组件:将 store 提供给整个应用
- useSelector:从 store 中获取状态(替代了旧版的 mapStateToProps)
- useDispatch:获取 dispatch 函数,用于分发 action
注意事项
- Redux 5 和 React-Redux 9 支持 React 18 的并发特性
- 没有使用 Redux Toolkit 时,需要手动处理不可变性
- 对于复杂应用,建议拆分 reducer(使用 combineReducers)
- 异步操作需要额外使用 redux-thunk 等中间件
3、处理异步 Action(使用 redux-thunk)
安装 redux-thunk:
npm install redux-thunk
假如你想实现一个异步的 action,比如从 API 获取数据,你可以这样写:
// asyncActions.js
export const fetchData = () => {return async (dispatch) => {dispatch({ type: 'FETCH_START' });try {const response = await fetch('https://api.example.com/data');const data = await response.json();dispatch({ type: 'FETCH_SUCCESS', payload: data });} catch (error) {dispatch({ type: 'FETCH_FAILURE', payload: error.message });}};
};
然后你需要在 reducer 中处理这些新的 action types。
补充建议
虽然原生 Redux 可用,但 Redux Toolkit(RTK) 是官方推荐的更现代、更简洁的 Redux 开发方式,它封装了最佳实践,大大减少了模板代码。如果你可以接受使用 RTK,建议优先考虑它。