Redux Action

2021-09-16 09:50 更新

Action

首先,让我们来给 action 下个定义。

Actions 是把数据从应用(译者注:这里之所以不叫 view 是因为这些数据有可能是服务器响应,用户输入或其它非 view 的数据 )传到 store 的有效载荷。它是 store 数据的惟一来源。用法是通过 store.dispatch() 把 action 传到 store。

添加新 todo 任务的 action 是这样的:

const ADD_TODO = 'ADD_TODO';
{
  type: 'ADD_TODO',
  text: 'Build my first Redux app'
}

Action 本质是 JavaScript 普通对象。我们约定,action 内使用一个字符串类型的 type 字段来表示将要执行的动作。多数情况下,type 会被定义成字符串常量。当应用规模越来越大时,建议使用单独的模块或文件来存放 action。

import { ADD_TODO, REMOVE_TODO } from '../actionTypes';
样板文件使用提醒

使用单独的模块或文件来定义 action type 常量并不是必须的,甚至根本不需要定义。对于小应用来说,使用字符串做 action type 更方便些。不过,在大型应用中最多把它们显式地定义成常量。参照 减少样板代码 获取保持代码干净的实践经验。

除了 type 字段外,action 对象的结构完全取决于你。参照 Flux 标准 Action 获取如何组织 action 的建议。

这时,我们还需要再添加一个 action type 来标记任务完成。因为数据是存放在数组中的,我们通过 index 来标识任务。实际项目中一般会在新建内容的时候生成惟一的 ID 做标识。

{
  type: COMPLETE_TODO,
  index: 5
}

action 中传递的数据越少越好。比如,这里传递 index 就比把整个任务对象传过去要好。

最后,再添加一个 action 类型来表示当前展示的任务状态。

{
  type: SET_VISIBILITY_FILTER,
  filter: SHOW_COMPLETED
}

Action 创建函数

Action 创建函数 就是生成 action 的方法。“action” 和 “action 创建函数” 这两个概念很容易混在一起,使用时最好注意区分。

传统的 Flux 实现中,当调用 action 创建函数时,一般会触发一个 dispatch,像这样:

function addTodoWithDispatch(text) {
  const action = {
    type: ADD_TODO,
    text
  };
  dispatch(action);
}

不同的是,Redux 中的 action 创建函数是 纯函数,它没有任何副作用,只是返回 action 对象而已。

function addTodo(text) {
  return {
    type: ADD_TODO,
    text
  };
}

这让代码更易于测试和移植。只需把 action 创建函数的结果传给 dispatch() 方法即可实例化 dispatch。

dispatch(addTodo(text));
dispatch(completeTodo(index));

或者创建一个 被绑定的 action 创建函数 来自动 dispatch:

const boundAddTodo = (text) => dispatch(addTodo(text));
const boundCompleteTodo = (index) => dispatch(CompleteTodo(index));

可以这样调用:

boundAddTodo(text);
boundCompleteTodo(index);

store 里能直接通过 store.dispatch() 调用 dispatch() 方法,但是多数情况下你会使用 react-redux 提供的 connect() 帮助器来调用。bindActionCreators() 可以自动把多个 action 创建函数 绑定到 dispatch() 方法上。

源码

actions.js

/*
 * action 类型
 */

export const ADD_TODO = 'ADD_TODO';
export const COMPLETE_TODO = 'COMPLETE_TODO';
export const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER';

/*
 * 其它的常量
 */

export const VisibilityFilters = {
  SHOW_ALL: 'SHOW_ALL',
  SHOW_COMPLETED: 'SHOW_COMPLETED',
  SHOW_ACTIVE: 'SHOW_ACTIVE'
};

/*
 * action 创建函数
 */

export function addTodo(text) {
  return { type: ADD_TODO, text };
}

export function completeTodo(index) {
  return { type: COMPLETE_TODO, index };
}

export function setVisibilityFilter(filter) {
  return { type: SET_VISIBILITY_FILTER, filter };
}

下一步

现在让我们 开发一些 reducers 来指定发起 action 后 state 应该如何更新。

高级用户建议

如果你已经熟悉这些基本概念且已经完成了这个示例,不要忘了看一下在 高级教程 中的 异步 actions,你将学习如何处理 AJAX 响应和如何把 action 创建函数组合成异步控制流。

以上内容是否对您有帮助:

在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号