【问题标题】:Show custom dialog setRouteLeaveHook or history.listenBefore react-router/redux?在 react-router/redux 之前显示自定义对话框 setRouteLeaveHook 或 history.listenBefore?
【发布时间】:2016-03-03 11:04:27
【问题描述】:

我似乎无法弄清楚如何显示自定义对话,而不是使用routeWillLeavehistory.listenBefore 使用的普通window.confirm。基本上我已经建立了一个通知系统并检查表单是否脏const { dispatch, history, dirty } = this.props;

如果表单是脏的,这意味着用户有未保存的更改。如果他们改变路线,我想显示我的通知,其中有两个按钮 STAYIGNORE,它们都可以使用 onClick 处理程序。

我花了一些时间在谷歌上搜索,但没有提到我如何使用routeWillLeave 完成此任务。我能找到的最接近的方法是使用 history.listenBefore 但是有文档说我需要这样做。

let history = createHistory({
  getUserConfirmation(message, callback) {
    callback(window.confirm(message)) // The default behavior
  }
})

但我正在使用 react-router 中的 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!"
  }
});

谢谢

【问题讨论】:

  • 我刚刚在这里回答了一个类似的问题:stackoverflow.com/a/35793421/52041
  • 谢谢你,只是出于好奇,你是如何想出这个解决方案的?您是否深入研究了 setRouterLeaveHook 是如何实现并重新实现它以提供 asyncv 版本或..?
  • 不,我只是根据 setRouterLeaveHook 的行为与一位同事进行了一些头脑风暴。

标签: reactjs react-router redux


【解决方案1】:

我决定使用的另一个解决方案是在正常的 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;
}

【讨论】:

  • 知道为什么不使用setTimeout 就没有更新道具吗?
  • 如果用户试图通过使用浏览器的后退按钮导航离开,这会不会很奇怪 -> 您的代码会将新位置推送到历史记录而不是返回历史?
猜你喜欢
  • 1970-01-01
  • 2016-09-08
  • 2017-04-05
  • 1970-01-01
  • 1970-01-01
  • 2017-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多