【问题标题】:Custom leave dialog in react-routerreact-router中的自定义离开对话框
【发布时间】:2016-09-08 14:39:26
【问题描述】:

我有一个表单,用户可以在其中编辑内容。如果用户有一些未保存的更改并想离开页面,我想给他一个自定义对话框,询问他是否确定。如果那么导航应该继续并且应该重置表单更改标志,否则用户应该留在页面上。

在这里你可以检查我当前正在检查这种情况的高阶组件。它正在工作,但函数 leave 返回一个字符串,然后 react-router 将在本机警报中显示该文本。

有没有一种方法可以在这里显示我的自定义对话框?并且我是否还可以获得警报的回调或类似内容,以便我可以调度一个告诉存储最新更改并不重要的事件。

import React, {Component, PropTypes} from "react";
import connectRouter from "./connectRouter";
import { connect } from "react-redux";
import {injectIntl, intlShape} from "react-intl";

export default function confirmLeave(RouteTargetComponent) {

  @injectIntl
  @connectRouter
  @connect((state, routing) => {
    return {
      studies: state.studies
    };
  })
  class ConfirmLeaveHOC extends Component { // HOC = Higher Order Component

    static propTypes = {
      router: PropTypes.object.isRequired,
      route: PropTypes.object.isRequired,
      dispatch: PropTypes.func.isRequired,
      intl: intlShape.isRequired,
      studies: PropTypes.object.isRequired,
    };

    leave = () => {
      if (this.props.studies.isChanged) {
        // lets stop the navigation
        return this.props.intl.formatMessage({ id: "confirmLeave" });
      }
      // continue the navigation
      return true;
    }

    componentDidMount() {
      this.props.router.setRouteLeaveHook(this.props.route, this.leave.bind(this));
    }

    render() {
      // render the component that requires auth (passed to this wrapper)
      return (<RouteTargetComponent {...this.props}/>);
    }
  }

  return ConfirmLeaveHOC;
}

【问题讨论】:

    标签: reactjs react-native react-router


    【解决方案1】:

    由于无法自定义浏览器对话框,因此您必须呈现一个单独的组件(例如引导模式)并使用回调来确定单击了哪个按钮以及要执行什么操作。

    实际上我最近遇到了同样的问题,我能够通过使用 routerWillLeave 和使用来自另一个组件的回调来解决它。

    表单组件

    routerWillLeave = (route) => {
      if (!this.waitingForConfirm && this._hasUnsavedChanges() && !this.clickedSave) {
        this.refs.confirmAlert._show( ((v) => {
          if (v) {
            this.context.router.push(route.pathname);
          }
          this.waitingForConfirm = false;
        }).bind(this));
        this.waitingForConfirm = true;
        return false;      
      }
    }
    

    不幸的是,像这样的自定义对话框的实现是相当痛苦的。我必须在这里使用 3 个变量来正确控制所需的行为:

    • waitingForConfirm - 当用户确认退出时防止逻辑第二次运行是必要的。具体来说,当回调运行并且我们执行this.context.router.push(route.pathname) 时,routerWillLeave 将再次运行(!),但由于我们已经确认导航,我们必须阻止此逻辑再次运行。

    • _hasUnsavedChanges() - 检查是否有任何输入字段已更改(没有理由询问是否没有要保存的更改)。

    • clickedSave - 如果用户点击了Save,不要要求确认 - 我们知道我们要离开。

    对话框组件

    _show = (callback) => {
      this.callback = callback;
      this.setState({show: true});
    }
    
    _hide = () => {
      this.setState({show: false});
      this.callback = null;
    }
    
    _dialogAction = (input) => {
      if (this.callback) {
        this.callback(input);
      }
      this._hide();
    }
    
    render() {
      return (
        ...
        <Button onClick={this._dialogAction.bind(this, true)}>Yes</Button>
        <Button onClick={this._dialogAction.bind(this, false)}>No</Button>
      );
    }
    

    显然,您必须自定义上述 sn-ps 以适合您的应用程序,但希望它能提供一些关于如何解决问题的见解。

    【讨论】:

    • 感谢this.context.router.push(route.pathname);帮了我很多
    【解决方案2】:

    一种不太复杂且更先进的方法是在您的组件上使用 setRouteLeaveHook。按照 react-router v2.4.0

     
        import React from 'react'
        import { withRouter } from 'react-router'
    
        const Page = React.createClass({
    
            componentDidMount() {
                this.props.router.setRouteLeaveHook(this.props.route, () => {
                   if (this.state.unsaved)
                     return 'You have unsaved information, are you sure you want to  
                     leave this page?'
               })
             }
    
             render() {
                return Stuff
             }
    
         })
    
         export default withRouter(Page)
    

    Here is the React-router version on their github page

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-10
      • 1970-01-01
      相关资源
      最近更新 更多