javascript - React.js,ES6,如何访问ES6类中的react-router Lifecycle?

标签 javascript reactjs ecmascript-6 react-router

我想使用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,我似乎缺少一些东西?非常感谢任何见解...

我的代码:

管理类(class)页面.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 类中设置路由离开钩子(Hook)。

问题已解决。

关于javascript - React.js,ES6,如何访问ES6类中的react-router Lifecycle?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37978515/

相关文章:

Javascript:history.back 在 XUL 应用程序中不起作用

javascript - 纯正则表达式解决方案,用于在无法依赖 document.createElement 的环境中从 HTML 字符串获取文本内容?

javascript - React Native localeCompare 不适用于 Android

javascript - React 渲染在属性中的嵌套对象上窒息

javascript - 在 Redux mapDispatchToProps 中使用组件状态或 props

javascript - 标记的模板文字的 TemplateObject 数组是否被其领域弱引用?

javascript - 使用 javascript 创建一个表

javascript - Electron 修改选项而不重新创建窗口

javascript - IIS 8.5 中托管的 AngularJS html5Mode 路由问题

javascript - 验证码验证问题