在上一篇文章中,我们实现了一个Redux商店,其中行动是同步的。在这篇文章中,我们将从相同的存储开始,使行动成为异步的。

状态
作为提醒,这里是我们的商店状态:
type Person = {
id: number;
name: string;
};
type AppState = {
people: Person[];
};
所以,我们的应用状态包含一个人的数组。
这个应用程序将被刻意简化,这样我们就可以专注于Redux商店以及React组件如何以强类型的方式与之交互。
允许商店与异步操作一起工作
我们将使用Redux Thunk来允许Redux与异步操作一起工作。这是我们在创建商店时定义的中间件:
function configureStore(): Store<AppState> {
const store = createStore(
rootReducer,
undefined,
applyMiddleware(thunk) );
return store;
}
applyMiddleware 是Redux的一个函数,它允许我们向商店添加中间件,而 是Redux Thunk的中间件。thunk
行动和行动创建者
我们的动作创建者现在将是异步的。这里是添加一个人的动作创建器:
const addPerson = (personName: string) => async (
dispatch: Dispatch<AddPersonAction>
) => {
await wait(200);
dispatch({
type: "AddPerson",
payload: personName,
} as const);
};
在我们的例子中,我们正在用一个wait 函数来伪造一个异步函数。
addPerson 函数返回一个函数而不是动作对象,因为它是同步函数。内部函数接收了一个参数,dispatch ,这是另一个用于调度动作的函数。这是一个很多的函数!
注意,我们用Dispatch<AddPersonAction> 明确了dispatch 参数的类型。Dispatch 是Redux的一个标准类型,我们把动作的类型AddPersonAction 传递给它。这里是AddPersonAction 的定义:
type AddPersonAction = {
readonly type: "AddPerson";
readonly payload: string;
};
这里是移除一个人的动作创建者:
type RemovePersonAction = {
readonly type: "RemovePerson";
readonly payload: number;
};
const removePerson = (id: number) => async (
dispatch: Dispatch<RemovePersonAction>
) => {
await wait(200);
dispatch({
type: "RemovePerson",
payload: id,
} as const);
};
减速器
reduceraction 参数类型的创建方式与同步版本不同:
type Actions =
| AddPersonAction
| RemovePersonAction;
我们在同步版本中推断了动作类型,但在这里我们明确地创建了这些类型。
减速器的功能与同步版本完全相同:
function peopleReducer(
state: Person[] = [],
action: Actions
) {
switch (action.type) {
case "AddPerson":
return state.concat({
id: state.length + 1,
name: action.payload,
});
case "RemovePerson":
return state.filter(
(person) => person.id !== action.payload
);
default:
neverReached(action);
}
return state;
}
function neverReached(never: never) {}
酷!"。
连接组件
将React组件连接到商店,与同步版本完全相同。useSelector ,用于从商店获取数据:
const people: Person[] = useSelector(
(state: AppState) => state.people
);
useDispatch 是用来调用存储动作的:
const dispatch = useDispatch();
...
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
dispatch(addPerson(newPerson));
...
};
...
const dispatchNewPerson = (id: number) => () => {
dispatch(removePerson(id));
};
...
<button onClick={dispatchNewPerson(person.id)}>Remove</button>
很好!
这个例子可以在CodeSandbox中找到:codesandbox.io/s/react-red…
包裹起来
Redux需要一个像Redux Thunk这样的库来处理异步操作。React组件与同步和异步动作的交互方式是一样的。主要的区别是在动作创建者方面。异步动作创建者返回一个最终派发动作对象的函数,而同步动作创建者立即返回动作对象。