How to use a custom component with react-router route transitions?

前端 未结 5 1531
生来不讨喜
生来不讨喜 2021-02-08 11:25

The article Confirming Navigation explains how to use a browser confirmation box in your transition hook. Fine. But I want to use my own Dialog box. If I were to use the methods

5条回答
  •  囚心锁ツ
    2021-02-08 11:48

    Here's my solution to the same. I made a custom dialog component that you can use to wrap any component in your app. You can wrap your header and this way have it present on all pages. It assumes you're using Redux Form, but you can simply replace areThereUnsavedChanges with some other form change checking code. It also uses React Bootstrap modal, which again you can replace with your own custom dialog.

    import React, { Component } from 'react'
    import { connect } from 'react-redux'
    import { withRouter, browserHistory } from 'react-router'
    import { translate } from 'react-i18next'
    import { Button, Modal, Row, Col } from 'react-bootstrap'
    
    // have to use this global var, because setState does things at unpredictable times and dialog gets presented twice
    let navConfirmed = false
    
    @withRouter
    @connect(
      state => ({ form: state.form })
    )
    export default class UnsavedFormModal extends Component {
      constructor(props) {
        super(props)
        this.areThereUnsavedChanges = this.areThereUnsavedChanges.bind(this)
        this.state = ({ unsavedFormDialog: false })
      }
    
      areThereUnsavedChanges() {
        return this.props.form && Object.values(this.props.form).length > 0 &&
          Object.values(this.props.form)
            .findIndex(frm => (Object.values(frm)
              .findIndex(field => field && field.initial && field.initial !== field.value) !== -1)) !== -1
      }
    
      render() {
        const moveForward = () => {
          this.setState({ unsavedFormDialog: false })
          navConfirmed = true
          browserHistory.push(this.state.nextLocation.pathname)
        }
        const onHide = () => this.setState({ unsavedFormDialog: false })
    
        if (this.areThereUnsavedChanges() && this.props.router && this.props.routes && this.props.routes.length > 0) {
          this.props.router.setRouteLeaveHook(this.props.routes[this.props.routes.length - 1], (nextLocation) => {
            if (navConfirmed || !this.areThereUnsavedChanges()) {
              navConfirmed = false
              return true
            } else {
              this.setState({ unsavedFormDialog: true, nextLocation: nextLocation })
              return false
            }
          })
        }
    
        return (
          
    {this.props.children} WARNING: unsaved changes Are you sure you want to leave the page without saving changes to the form?
    ) } }

提交回复
热议问题