快速创建Action

在Redux中Action实际上就是一个有着特定结构的普通Javascript对象。在习惯上,Action的基本类型就是{ type: string, payload: any }

在Redux使用到项目开发中以后,经历了一个首先定义大量Action Type字符串,然后过渡到利用Action构建函数根据需要动态的创建Action。例如以下示例所示。

const INCREASE = 'counter/increase';

function counterIncrease(amount: number) {
  return {
    type: INCREASE,
    payload: amount
  };
}

// 定义Action构建函数以后,就可以使用以下形式创建Action
const action = counterIncrease(1);

因为这种Action的结构形式和创建方法已经基本上得到了绝大多数Redux使用者的认可和习惯,所以Redux Toolkit根据这个Action的结构形式和创建方法,引入了一个能够快速创建Action的辅助函数createAction

利用createAction这个辅助函数来重写上面的示例,就会使代码变得十分简练。

import { createAction } from '@reduxjs/toolkit';

// createAction创建的是一个生成器函数,返回的函数在执行以后才会返回一个Action生成函数。
const counterIncreaseAction = createAction<number | undefined>('counter/increase');

// 调用执行生成器函数可以生成一个Action,如果提供任何参数生成的Action就不会携带payload属性。
// 在这个示例中生成的action内容是 \{ type: 'counter/increase' \}
const counterIncrease = counterIncreaseAction();

// 传递一个参数来调用生成器函数可以生成一个带有payload属性的Action对象。
// 在这个示例中,action的内容是 \{ type: 'counter/increase', payload: 1 \}
const action = counterIncrease(1);

createAction函数的函数签名是createAction(type, preparedAction?),所以除了可以直接指定一个type参数来快速定义一个Action生成器函数以外,还可以通过传递一个自定义的Action准备函数来为默认生成的Action携带的内容。以下示例在之前示例的基础上为Action自定义了要携带的内容。

import { createAction } from '@reduxjs/toolkit';

const counterIncreaseAction = createAction('counter/increase', (amount: number, text: string) => ({
  payload: {
    amount,
    message: text,
    createdAt: new Date().getTime()
  }
}));

// 调用这个生成器函数可以直接生成一个Action对象。
// 在这个示例中,action的内容是 \{ type: 'counter/increase', payload: \{ amount: 1, message: 'hello', createdAt: 1652523758732 \} \}
const increaseAction = counterIncreaseAction(1, 'Hello');

Warning

注意,createAction所构建的Action只能使用字符串作为Action类型,不能创建非字符串类型的Action。任何传入的非字符串类型的Action类型值,都将被转换成字符串。

当具备了一些Action以后,就可以前进到定义Reducer的步骤了。