显示自定义对话框setRouteLeaveHook或history.listenBefore react-router/redux?
问题描述:
我似乎无法弄清楚如何显示自定义对话而不是使用routeWillLeave
和history.listenBefore
使用的正常window.confirm
。基本上我已经建立了一个通知系统,并检查表单是否脏const { dispatch, history, dirty } = this.props;
显示自定义对话框setRouteLeaveHook或history.listenBefore react-router/redux?
如果表单很脏,则表示用户有未保存的更改。如果他们改变路线,我想显示我的通知,其中将有两个按钮STAY
,IGNORE
,它们都可以采用onClick处理程序。
我花了一点时间使用Google搜索,还没有碰到任何提及我可以如何使用routeWillLeave
来完成此操作。我能找到的最接近的东西是使用history.listenBefore
但是有文档说我需要这样做。
let history = createHistory({
getUserConfirmation(message, callback) {
callback(window.confirm(message)) // The default behavior
}
})
但是我使用browserHistory从反应路由器启动我的商店const history = syncHistoryWithStore(browserHistory, store);
如何停止链接被点击后的路线变化,利用我的自定义通知系统,并根据显示的通知点击哪个按钮或者转换到新路线还是停留?
下面是我的通知系统如何工作的示例以及显然无法工作的指导方向,因为所有返回的都是默认情况下显示在window.confirm对话框中的字符串。
history.listenBefore((location) => {
if(this.props.dirty){
const acceptBtn = {
title: 'STAY',
handler: ignoreRouteChange() //This can be any function I want
}
const denyBtn = {
title: 'IGNORE',
handler: continueRouteChange() //This can be any function I want
}
return dispatch(addNotification({
message: 'You have unsaved changes!',
type: NOTIFICATION_TYPE_WARNING,
duration: 0,
canDismiss: false,
acceptBtn,
denyBtn
}));
return "Usaved changes!"
}
});
感谢
答
,我已决定采用另一种方案是在正常setRouterLeaveHook回调返回false,然后显示我的对话框,并使用nextLocation传递给回调推视按钮的下一个路由选择。
router.setRouteLeaveHook(route, this.routerWillLeave.bind(this));
routerWillLeave(nextLocation){
let { dirty, dispatch, resetForm } = this.props;
if (dirty) {
let dialog = {
id: Date.now(),
showTitle: true,
titleContent: 'Unsaved Changes',
titleIcon: 'fa fa-warning',
content: <span>You have <strong>unsaved</strong> changes! <strong>Discard</strong> them?</span>,
type: 'confirm',
handleCloseClick: (e) => {
e.preventDefault();
dispatch(closeDialog());
},
acceptBtn: {
title: 'Okay',
handler: (e) => {
e.preventDefault();
resetForm();
// Wait for call stack to unwind and then execute
// the following which will now have the updated values.
setTimeout(() => {
dispatch(push(nextLocation));
dispatch(closeDialog());
}, 0);
}
},
denyBtn: {
title: 'Deny',
handler: (e) => {
e.preventDefault();
dispatch(closeDialog());
}
}
}
dispatch(addDialogWindow(dialog));
dispatch(openDialog(false, (e) => dispatch(closeDialog()), false));
return false;
}
return true;
}
我刚才已经回答了类似的问题在这里:http://stackoverflow.com/a/35793421/52041 –
感谢您的,只是出于好奇你是怎么想出了这个解决方案?你有没有深入了解setRouterLeaveHook是如何实现的,并重新实现它以提供一个asynv版本或..? – Deep
不,我只是根据setRouterLeaveHook的行为,与同事进行了一次头脑风暴。 –