Redux 工程化:Action Creator 的创建
基本概念
Action Creator 是一个函数,它创建并返回一个 action 对象。使用 Action Creator 可以带来以下好处:
- 集中管理 action 类型
- 减少手动编写 action 对象时的错误
- 便于处理异步操作
- 提高代码可维护性
基础 Action Creator
// 基础形式
function addTodo(text) {
return {
type: 'ADD_TODO',
payload: {
text,
id: Date.now(),
completed: false
}
};
}
工程化实践
1. 常量管理 Action 类型
// actionTypes.js
export const ADD_TODO = 'ADD_TODO';
export const TOGGLE_TODO = 'TOGGLE_TODO';
export const DELETE_TODO = 'DELETE_TODO';
// actions.js
import { ADD_TODO, TOGGLE_TODO, DELETE_TODO } from './actionTypes';
export const addTodo = (text) => ({
type: ADD_TODO,
payload: { text, id: Date.now(), completed: false }
});
export const toggleTodo = (id) => ({
type: TOGGLE_TODO,
payload: { id }
});
export const deleteTodo = (id) => ({
type: DELETE_TODO,
payload: { id }
});
2. 使用 payload 规范
推荐使用 Flux Standard Action (FSA) 规范:
type
: 必须的字符串payload
: 可选的数据error
: 可选的布尔值,表示是否是错误meta
: 可选的额外信息
3. 异步 Action Creator
对于异步操作,可以使用 Redux Thunk 或 Redux Saga 等中间件:
// 使用 Redux Thunk
export const fetchTodos = () => {
return async (dispatch) => {
dispatch({ type: 'FETCH_TODOS_REQUEST' });
try {
const response = await api.getTodos();
dispatch({
type: 'FETCH_TODOS_SUCCESS',
payload: response.data
});
} catch (error) {
dispatch({
type: 'FETCH_TODOS_FAILURE',
payload: error,
error: true
});
}
};
};
4. Action Creator 工厂函数
对于相似的 action,可以创建工厂函数:
const createAsyncActions = (type) => {
return {
request: (payload) => ({ type: `${type}_REQUEST`, payload }),
success: (payload) => ({ type: `${type}_SUCCESS`, payload }),
failure: (error) => ({ type: `${type}_FAILURE`, payload: error, error: true })
};
};
// 使用
const todoActions = createAsyncActions('TODO');
// todoActions.request(), todoActions.success(), todoActions.failure()
5. 使用 redux-actions 库
redux-actions
提供了 createAction
和 handleActions
等实用函数:
import { createAction } from 'redux-actions';
export const addTodo = createAction('ADD_TODO', text => ({
text,
id: Date.now(),
completed: false
}));
// 使用
dispatch(addTodo('Learn Redux'));
最佳实践
- 命名规范:使用全大写和下划线命名 action 类型,如
FETCH_USER_SUCCESS
- 单一职责:每个 action creator 只做一件事
- 纯函数:确保 action creator 是纯函数,不产生副作用
- 文档注释:为每个 action creator 添加清晰的注释
- 测试:为 action creator 编写单元测试
目录结构建议
store/
actions/
index.js // 导出所有 action creator
todoAction.js // todo 相关的 action
userAction.js // 用户相关的 action
reducers/
index.js
todoReducer.js // todo 相关的 action
userReducer.js // 用户相关的 action
actionTypes.js // 所有 action 类型常量
index.js
命名导出及使用方式
// actions/index.js
// 从各个模块导入 action creators
import * as todoActions from './todoActions';
import * as userActions from './userActions';
import * as productActions from './productActions';
// 集中导出所有 action creators
export {
todoActions,
userActions,
productActions
};
// 也可以选择平铺导出(根据项目规模决定)
export * from './todoActions';
export * from './userActions';
export * from './productActions';
// 在组件中使用------------------------------------
// 使用命名空间方式
import { todoActions, userActions } from '../actions';
dispatch(todoActions.addTodo('Learn Redux'));
dispatch(userActions.login({ username: 'test', password: '123' }));
// 使用平铺导出方式
import { addTodo, login } from '../actions';
dispatch(addTodo('Learn Redux'));
dispatch(login({ username: 'test', password: '123' }));