我想使用react-router生命周期来设置过渡-在用户尝试通过未保存的更改离开表单时通知用户。

我对使用此功能特别感兴趣:

  routerWillLeave(nextLocation) {
    if(!this.state.isSaved)
      return 'Your work is not saved! Are you sure you want to leave?'
  }


我尝试使用'react-mixin'语法:

reactMixin.onClass(ManageCoursePage, Lifecycle);


我得到这个错误:

Invariant Violation: The Lifecycle mixin must be used on either a) a <Route component> or b) a descendant of a <Route component> that uses the RouteContext mixin


似乎我缺少有关RouteComponents和RouteContext的东西?非常感谢任何见解...

我的代码:

ManageCoursePage.js

import React, {PropTypes} from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import reactMixin from 'react-mixin';
import { Lifecycle } from 'react-router';
import {authorsFormattedForDropdown} from '../../selectors/selectors';
import * as courseActions from '../../actions/courseActions';
import * as authorActions from '../../actions/authorActions';
import CourseForm from './CourseForm';

export class ManageCoursePage extends React.Component {
    constructor(props, context) {
    super(props, context);

    this.state = {
      course: Object.assign({}, this.props.course),
      errors: {},
      saving: false

    };

    this.routerWillLeave = this.routerWillLeave.bind(this);
    this.updateCourseState = this.updateCourseState.bind(this);
    this.saveCourse = this.saveCourse.bind(this);
  }


  routerWillLeave(nextLocation) {
    if(!this.state.isSaved)
      return 'Your work is not saved! Are you sure you want to leave?'
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.course.id != nextProps.course.id) {
      //Necessary to populate form when existing course is loaded directly
      this.setState({course: Object.assign({}, nextProps.course)});
    }

  }

  updateCourseState(event) {
    const field = event.target.name;
    let course = this.state.course;
    course[field] = event.target.value;
    console.log("change");
    return this.setState({course: course});

  }

  courseFormIsValid() {
    let formIsValid = true;
    let errors = {};

    if(this.state.course.title.length < 5) {
      errors.title = 'Title must be at least 5 characters.';
      formIsValid = false;
    }

    this.setState({errors: errors});
    return formIsValid;
  }

  saveCourse(event){
    event.preventDefault();

    if (!this.courseFormIsValid()) {
      return;
    }

    this.setState({saving: true});

    this.props.actions.saveCourse(this.state.course)
      .then(() => this.redirect())
      .catch(error => {
        toastr.error(error);
        this.setState({saving: false});
      });
  }



  redirect() {
    this.setState({saving: false});
    toastr.success('Course saved');

    this.context.router.push('/courses');
  }

  render() {
    return (
        <CourseForm
          allAuthors={this.props.authors}
          onChange={this.updateCourseState}
          onSave={this.saveCourse}
          course={this.state.course}
          errors={this.state.errors}
          saving={this.state.saving}
        />
    );
  }
}

reactMixin.onClass(ManageCoursePage, Lifecycle);


ManageCoursePage.propTypes = {
  course: PropTypes.object.isRequired,
  authors: PropTypes.array.isRequired,
  actions: PropTypes.object.isRequired
};

ManageCoursePage.contextTypes = {
  router: PropTypes.object
};

function getCourseById(courses, id){

  const course = courses.filter(course => course.id == id);
  if (course) return course[0]; //filter returns an array, so you have to grab the first value.
  return null;
}
function mapStateToProps(state, ownProps) {

  const courseId = ownProps.params.id; // from the path '/course/:id'
  let course = {id: '', watchHref: '', title: '', authorId: '', length: '', category: ''};

  if (courseId && state.courses.length > 0) {
    course = getCourseById(state.courses, courseId);
  }

  return {
    course: course,
    authors: authorsFormattedForDropdown(state.authors)

  };
}


function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(courseActions, dispatch)
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(ManageCoursePage);


routes.js

import React from 'react';
import { Route, IndexRoute } from 'react-router';
import App from './components/App';
import HomePage from './components/home/HomePage';
import AboutPage from './components/about/AboutPage';
import CoursesPage from './components/course/CoursesPage';
import AuthorsPage from './components/author/AuthorsPage';
import ManageAuthorPage from './components/author/ManageAuthorPage';
import ManageCoursePage from './components/course/ManageCoursePage'; //eslint-disable-line import/no-named-as-default

export default (

   <Route path="/" component={App}>
    <IndexRoute component={HomePage} />
    <Route path="about" component={AboutPage} />
    <Route path="courses" component={CoursesPage} />
    <Route path="course" component={ManageCoursePage} />
    <Route path="course/:id" component={ManageCoursePage} />
    <Route path="authors" component={AuthorsPage} />
    <Route path="author" component={ManageAuthorPage} />
    <Route path="author/:id" component={ManageAuthorPage} />
  </Route>
);

最佳答案

我能够使用this.context.route.setRouteLeaveHook在我的ES6类中设置路由离开挂钩。

问题解决了。

09-11 18:23