【问题标题】:React.js, ES6, how to access react-router Lifecycle inside ES6 class?React.js,ES6,如何访问 ES6 类中的 react-router 生命周期?
【发布时间】:2016-10-25 00:20:34
【问题描述】:

我想使用 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>
);

【问题讨论】:

    标签: javascript reactjs ecmascript-6 react-router


    【解决方案1】:

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

    问题解决了。

    【讨论】:

      【解决方案2】:

      您可能可以在&lt;Route /&gt; 组件中使用onLeave 属性。尝试类似:

      export default (
        <Route path="/" component={App}>
          <Route path="course/:id" component={ManageCoursePage} onLeave={handleOnRouteLeave} />
        </Route>
      )
      
      function handleOnRouteLeave () {
        // do whatever logic you need to do when leaving the route
      }
      

      更多信息:<Route> component API: onLeave

      【讨论】:

      • 你不能阻止onLeave中的任何东西..你可以做一些处理
      猜你喜欢
      • 2015-10-10
      • 2019-08-11
      • 1970-01-01
      • 2017-11-04
      • 2015-11-20
      • 2016-05-06
      • 2018-06-30
      • 2021-03-20
      相关资源
      最近更新 更多