我尝试使用redux和native promise构建一个通用的confirm组件。我在这里阅读Dan Abramovs解决方案:How can I display a modal dialog in Redux that performs asynchronous actions?但我正在寻找更通用的方法。 基本上我想这样做:
confirm({
type: 'warning',
title: 'Are you sure?',
description: 'Would you like to do this action?',
confirmLabel: 'Yes',
abortLabel: 'Abort'
})
.then(() => {
// do something after promise is resolved
})
确认方法基本上打开模态并返回一个promise。在承诺内部,我订阅了我的redux商店,听取状态变化并解决或拒绝承诺:
export const confirm = function(settings) {
// first dispatch openConfirmModal with given props
store.dispatch(
openConfirmModal({
...settings
})
);
// return a promise that subscribes to redux store
// see: http://redux.js.org/docs/api/Store.html#subscribe
// on stateChanges check for resolved/rejected
// if resolved or rejected:
// - dispatch closeConfirmModal
// - resolve or reject the promise
// - unsubscribe to store
return new Promise((resolve, reject) => {
function handleStateChange() {
let newState = store.getState();
if (newState.confirmModal.resolved) {
store.dispatch(closeConfirmModal());
resolve();
unsubscribe();
}
if (newState.confirmModal.rejected) {
store.dispatch(closeConfirmModal());
reject();
unsubscribe();
}
}
let unsubscribe = store.subscribe(handleStateChange);
})
}
我的确认组件已连接到redux store,并且在某种布局组件中包含一次 - 因此它可用于应用程序中的所有路径:
class ConfirmModal extends Component {
constructor(props) {
super(props)
}
confirm() {
this.props.dispatch(resolveConfirmModal());
}
abort() {
this.props.dispatch(rejectConfirmModal());
}
render() {
// my modal window
}
}
export default connect(
state => ({
confirmModal: state.confirmModal
})
)(ConfirmModal);
Reducer / Action看起来像这样:
export const openConfirmModal = (settings) => {
return {
type: 'OPEN_CONFIRM_MODAL',
settings
};
};
export const resolveConfirmModal = () => {
return {
type: 'RESOLVE_CONFIRM_MODAL'
};
};
export const rejectConfirmModal = () => {
return {
type: 'REJECT_CONFIRM_MODAL'
};
};
export const closeConfirmModal = () => {
return {
type: 'CLOSE_CONFIRM_MODAL'
};
};
const initialState = {
open: false,
type: 'info',
title: 'Are you sure?',
description: 'Are you sure you want to do this action?',
confirmLabel: 'Yes',
abortLabel: 'Abort',
};
export const ConfirmModalReducer = (state = initialState, action) => {
switch (action.type) {
case 'OPEN_CONFIRM_MODAL':
return { ...action.settings, open: true };
case 'RESOLVE_CONFIRM_MODAL':
return { ...state, resolved: true };
case 'REJECT_CONFIRM_MODAL':
return { ...state, rejected: true };
case 'CLOSE_CONFIRM_MODAL':
return initialState;
default:
return state;
}
};
redux部分正在运行。我的确认窗口可以打开/关闭,并根据我的选项进行渲染。但是我如何在我的确认方法中定义一个可以在我的组件中解决的承诺?我如何连接所有东西?
找到了一个与我一直在寻找的解决方案:
您怎么看?
答案 0 :(得分:1)
嗯,你可以做到,但它不会很漂亮。基本上,您需要在inputDate
旁边有一张优秀承诺的地图:
confirm()
然后再说:
var outstandingModals = {}
const confirm = function(settings) {
return new Promise((resolve, reject) => {
let id = uuid.v4();
outstandingModals = resolve;
store.dispatch(
openConfirmModal({
...settings,
confirmationId: id,
})
);
}
像我说的那样 - 丑陋。我认为你不能比使用承诺更好。
但是你可以通过不使用promises来做得更好。我要做的只是在必要时渲染一个确认组件,比如说:
case 'CLOSE_CONFIRM_MODAL':
let resolve = outstandingModals[state.confirmationId];
if (resolve) {
resolve();
delete outstandingModals[state.confirmationId];
}
return initialState;
render() {
return <div>
... My stuff ...
{confirmationNecessary && <Confirm text='Are you sure?' onAction={this.thenConfirmed}/>}
</div>
}
可以来自confirmationNecessary
或来自商店。
答案 1 :(得分:1)
我写了一篇博文,讨论了管理“泛型”模式的一种可行方法,如:http://blog.isquaredsoftware.com/2016/11/posts-on-packtpub-generic-redux-modals-and-building-better-bundles/。
基本思想是,请求模态的代码可以包含作为道具的预先写入的动作,并且模态可以在关闭后调度该动作。
在https://github.com/AKolodeev/redux-promising-modals还有一个看起来很有趣的库,似乎是通过中间件实现模态结果的承诺。
答案 2 :(得分:0)
可能如此:)
export const MsgBox = {
okCancel : s =>
new Promise((ok, cancel) =>
confirm(s) ? ok() : cancel() ),
......etc