显示自定义对话框setRouteLeaveHook或history.listenBefore react-router/redux?

问题描述:

我似乎无法弄清楚如何显示自定义对话而不是使用routeWillLeavehistory.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!" 
    } 
}); 

感谢

+1

我刚才已经回答了类似的问题在这里:http://*.com/a/35793421/52041 –

+0

感谢您的,只是出于好奇你是怎么想出了这个解决方案?你有没有深入了解setRouterLeaveHook是如何实现的,并重新实现它以提供一个asynv版本或..? – Deep

+0

不,我只是根据setRouterLeaveHook的行为,与同事进行了一次头脑风暴。 –

,我已决定采用另一种方案是在正常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; 
} 
+0

任何想法为什么道具没有使用'setTimeout'没有更新? – Yuri

+0

在用户试图通过使用浏览器的后退按钮导航离开的情况下,这种行为不会很奇怪 - >您的代码会将新位置推到历史记录上,而不是回到历史记录中? – nzjoel