Redux和Thunk的通用模态
我一直在研究使用 React、Redux 和 Thunk 创建通用模态。理想情况下,我的状态如下所示:
export interface ConfirmModalState {
isOpened: boolean;
onConfirm: null | Function
}
export const initialConfirmModalState: ConfirmModalState = {
isOpened: false,
onConfirm: null
};
然而,这意味着将不可序列化的数据放入状态,这似乎是非常不鼓励的。
我已经阅读了markerikson 的一篇很棒的博文。但是,我认为提议的解决方案不适用于异步操作和 Thunk。
你建议如何解决这个问题?
回答
我实际上写了你链接的帖子,几年后我写了那个帖子的扩展版本:
实用 Redux,第 10 部分:管理模式和上下文菜单。
自从我写那篇文章以来,我自己实际上已经实现了这种方法的几种变体,我发现的最佳解决方案是添加一个自定义中间件,当您发送“显示模式”操作时返回一个承诺,并解决承诺对话框关闭时带有“返回值”。
在https://github.com/AKolodeev/redux-promising-modals 上有这种方法的现有实现。我最终做出了自己的实现。我在https://gist.github.com/markerikson/8cd881db21a7d2a2011de9e317007580的要点中有一个我自己开发的方法的部分版本,中间件大致如下:
export const dialogPromiseMiddleware: Middleware<DialogPromiseDispatch> = storeAPI => {
const dialogPromiseResolvers: Record<string, Resolver> = {};
return next => (action: AnyAction) => {
switch (action.type) {
// Had to resort to `toString()` here due to https://github.com/reduxjs/redux-starter-kit/issues/157
case showDialogInternal.toString(): {
next(action);
let promiseResolve: Resolver;
const dialogPromise = new Promise((resolve: Resolver) => {
promiseResolve = resolve;
});
dialogPromiseResolvers[action.payload.id] = promiseResolve!;
return dialogPromise;
}
case closeDialog.toString(): {
next(action);
const {id, values} = action.payload;
const resolver = dialogPromiseResolvers[id];
if (resolver) {
resolver(values);
}
delete dialogPromiseResolvers[id];
break;
}
default:
return next(action);
}
};
};
(注意:当我遇到一些 TS 语法问题以使其正常工作时,我提出了这个要点,所以很可能它不会 100% 开箱即用。RTK 现在还包括一些 .match()在这里有用的动作匹配实用程序。但是,它显示了基本方法。)
在一个组件中的粗略用法是:
const closedPromise = dispatch(showDialog("TestDialog", {dialogNumber : counter});
const result = await closedPromise
// do something with the result
这样您就可以在要求首先显示对话框的地方编写“确认时”逻辑。