簡體   English   中英

React.js,ES6,如何在ES6類內部訪問react-router生命周期?

[英]React.js, ES6, how to access react-router Lifecycle inside ES6 class?

我想使用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類中設置路由離開鈎子。

問題解決了。

您可能可以在<Route />組件中使用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>組件API:onLeave

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM