Reactjs 显示自定义对话框SetRouteLaveHook或history.listenBefore react router/redux?
我似乎不知道如何使用常规的Reactjs 显示自定义对话框SetRouteLaveHook或history.listenBefore react router/redux?,reactjs,react-router,redux,Reactjs,React Router,Redux,我似乎不知道如何使用常规的窗口来显示自定义对话。请确认路线将离开和历史。在使用之前先听。基本上,我已经构建了一个通知系统,并检查表单是否为dirtyconst{dispatch,history,dirty}=this.props 如果表单是脏的,则表示用户有未保存的更改。如果他们改变路线,我想显示我的通知,它将有两个按钮停留,忽略,这两个按钮都可以使用onClick处理程序 我花了一点时间在谷歌上搜索,没有发现任何关于如何使用routeWillLeave实现这一点的信息。我能找到的最接近的方法就
窗口来显示自定义对话。请确认路线将离开和历史。在使用之前先听。基本上,我已经构建了一个通知系统,并检查表单是否为dirtyconst{dispatch,history,dirty}=this.props代码>
如果表单是脏的,则表示用户有未保存的更改。如果他们改变路线,我想显示我的通知,它将有两个按钮停留
,忽略
,这两个按钮都可以使用onClick处理程序
我花了一点时间在谷歌上搜索,没有发现任何关于如何使用routeWillLeave
实现这一点的信息。我能找到的最接近的方法就是使用历史记录。在之前听医生说我需要这样做
let history = createHistory({
getUserConfirmation(message, callback) {
callback(window.confirm(message)) // The default behavior
}
})
但是我正在使用react路由器的browserHistory来启动我的存储const history=syncHistoryWithStore(browserHistory,存储)代码>
单击链接后,我如何停止路线更改,使用自定义通知系统显示通知,并根据单击的按钮切换到新路线或停留
下面是我的通知系统如何工作的一个例子,我的方向显然不起作用,因为所有这些返回的都是一个字符串,显示在窗口中。默认情况下,确认对话框
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;
}
router.setRouteLeaveHook(route,this.routerWillLeave.bind(this));
routerWillLeave(下一个位置){
让{dirty,dispatch,resetForm}=this.props;
如果(脏的){
让对话={
id:Date.now(),
节目名称:真的,
标题内容:“未保存的更改”,
标题:“足总警告”,
内容:您有未保存的更改!放弃更改?,
键入:“确认”,
handleCloseClick:(e)=>{
e、 预防默认值();
调度(closeDialog());
},
接受BTN:{
标题:"好",,
处理者:(e)=>{
e、 预防默认值();
resetForm();
//等待调用堆栈展开,然后执行
//以下内容现在将具有更新的值。
设置超时(()=>{
调度(推送(下一个位置));
调度(closeDialog());
}, 0);
}
},
denyBtn:{
标题:“拒绝”,
处理者:(e)=>{
e、 预防默认值();
调度(closeDialog());
}
}
}
调度(addDialogWindow(dialog));
调度(openDialog(false,(e)=>dispatch(closeDialog()),false));
返回false;
}
返回true;
}
我刚才在这里回答了一个类似的问题:谢谢你,只是出于好奇,你是如何想出这个解决方案的?您是否深入研究了setRouterLeaveHook是如何实现的,并重新实现了它以提供asynv版本或..?没有,我只是与一位同事进行了一些头脑风暴,基于setRouterLeaveHook的行为。你知道为什么道具在没有使用setTimeout
的情况下还没有更新吗?如果用户试图使用浏览器的“后退”按钮导航,这不是很奇怪吗->你的代码会将一个新位置推到历史记录上,而不是回到历史记录中?