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实现这一点的信息。我能找到的最接近的方法就

我似乎不知道如何使用常规的
窗口来显示自定义对话。请确认
路线将离开
历史。在使用之前先听。基本上,我已经构建了一个通知系统,并检查表单是否为dirty
const{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
的情况下还没有更新吗?如果用户试图使用浏览器的“后退”按钮导航,这不是很奇怪吗->你的代码会将一个新位置推到历史记录上,而不是回到历史记录中?