State 结构设计
- 模块化设计:
- 将整个应用的状态按模块进行划分,例如用户模块(
user
)、订单模块(order
)、实时数据模块(realtimeData
)等。这样每个模块的状态相对独立,便于维护和管理。
- 示例:
{
user: {
userInfo: {},
role: '',
isLoggedIn: false
},
order: {
orders: [],
selectedOrder: null
},
realtimeData: {
dataStream: []
}
}
- 遵循单一数据源原则:整个应用只有一个
state
树,不同模块的状态在这个树中有各自的分支,避免数据冗余和不一致。
Actions 的组织方式
- 按模块分类:为每个模块定义相应的
action
类型和 action
创建函数。例如,用户模块的 action
可能有 LOGIN_SUCCESS
、LOGOUT
等;订单模块可能有 FETCH_ORDERS_SUCCESS
、CREATE_ORDER
等。
const LOGIN_SUCCESS = 'LOGIN_SUCCESS';
const LOGOUT = 'LOGOUT';
export const loginSuccess = (userInfo, role) => ({
type: LOGIN_SUCCESS,
payload: { userInfo, role }
});
export const logout = () => ({
type: LOGOUT
});
- 使用常量定义
action
类型:这样可以避免拼写错误,同时便于在整个应用中统一管理和维护 action
类型。
Reducers 的拆分与组合
- 拆分:
- 每个模块有自己独立的
reducer
,专注于处理该模块相关的 action
。例如,用户模块的 reducer
只处理与用户登录、登出、权限等相关的 action
。
- 示例(用户模块
reducer
):
import { LOGIN_SUCCESS, LOGOUT } from './actions';
const initialState = {
userInfo: {},
role: '',
isLoggedIn: false
};
const userReducer = (state = initialState, action) => {
switch (action.type) {
case LOGIN_SUCCESS:
return {
...state,
userInfo: action.payload.userInfo,
role: action.payload.role,
isLoggedIn: true
};
case LOGOUT:
return {
...state,
userInfo: {},
role: '',
isLoggedIn: false
};
default:
return state;
}
};
export default userReducer;
- 组合:使用
combineReducers
函数将各个模块的 reducer
组合成一个根 reducer
。
import { combineReducers } from'redux';
import userReducer from './userReducer';
import orderReducer from './orderReducer';
import realtimeDataReducer from './realtimeDataReducer';
const rootReducer = combineReducers({
user: userReducer,
order: orderReducer,
realtimeData: realtimeDataReducer
});
export default rootReducer;
处理异步操作
- 使用
redux - thunk
中间件:
- 它允许
action
创建函数返回一个函数而不是一个普通的 action
对象,这个函数可以进行异步操作,例如发起 API 请求。
- 示例(获取订单列表的异步操作):
import { FETCH_ORDERS_SUCCESS, FETCH_ORDERS_FAILURE } from './actions';
import axios from 'axios';
export const fetchOrders = () => {
return async (dispatch) => {
try {
const response = await axios.get('/api/orders');
dispatch({
type: FETCH_ORDERS_SUCCESS,
payload: response.data
});
} catch (error) {
dispatch({
type: FETCH_ORDERS_FAILURE,
payload: error.message
});
}
};
};
- 处理 loading 状态:在
state
中添加 loading
字段来表示异步操作的状态,在异步操作开始时设置为 true
,成功或失败时设置为 false
。这样可以在 UI 中显示加载指示器。
- 示例(订单模块
state
增加 loading
字段):
{
orders: [],
selectedOrder: null,
loading: false
}
- 在 `reducer` 中处理 `loading` 状态:
import { FETCH_ORDERS_SUCCESS, FETCH_ORDERS_FAILURE, FETCH_ORDERS_REQUEST } from './actions';
const initialState = {
orders: [],
selectedOrder: null,
loading: false
};
const orderReducer = (state = initialState, action) => {
switch (action.type) {
case FETCH_ORDERS_REQUEST:
return {
...state,
loading: true
};
case FETCH_ORDERS_SUCCESS:
return {
...state,
orders: action.payload,
loading: false
};
case FETCH_ORDERS_FAILURE:
return {
...state,
loading: false
};
default:
return state;
}
};
export default orderReducer;
中间件的选择与使用
redux - thunk
:如上述处理异步操作所述,用于处理异步 action
,简单易用,适合大多数异步场景。
redux - saga
:当异步操作逻辑复杂,需要处理多个异步任务的并发、顺序执行等情况时,可以考虑使用 redux - saga
。它使用生成器函数来管理异步操作,使异步逻辑更易于维护和测试。
- 示例(使用
redux - saga
获取订单列表):
import { call, put, takeEvery } from'redux - saga/effects';
import { FETCH_ORDERS_SUCCESS, FETCH_ORDERS_FAILURE } from './actions';
import axios from 'axios';
function* fetchOrdersSaga() {
try {
const response = yield call(axios.get, '/api/orders');
yield put({
type: FETCH_ORDERS_SUCCESS,
payload: response.data
});
} catch (error) {
yield put({
type: FETCH_ORDERS_FAILURE,
payload: error.message
});
}
}
export function* orderSaga() {
yield takeEvery('FETCH_ORDERS_REQUEST', fetchOrdersSaga);
}
redux - logger
:用于开发调试,它可以记录 action
以及 state
的变化,方便追踪应用状态的改变。在生产环境中可以移除该中间件以提高性能。
import { createStore, applyMiddleware } from'redux';
import logger from'redux - logger';
import rootReducer from './rootReducer';
const store = createStore(rootReducer, applyMiddleware(logger));