2016-06-22 21 views
0

私はリアクション・ルータ・ライフサイクルを使用して遷移を設定します。保存されていない変更があるフォームから移動しようとしたときにユーザーに知らせるためです。React.js、ES6、ES6クラス内の反応ルータライフサイクルへのアクセス方法

私はこの機能を使用することに特に興味があります:私は '反応し、ミックスイン' を構文を使用してみました

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

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おそらく<Route />コンポーネントでonLeave小道具を使用することができます

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> 
); 

答えて

0

:任意の洞察力はずっと...

私のコードを高く評価しています。以下のようなものを試してみてください:

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 
} 

さらに詳しい情報:私は私のES6クラス内からのルート休暇のフックを設定するthis.context.route.setRouteLeaveHookを使用することができました<Route> component API: onLeave

+0

あなたはonLeaveで何かを防ぐことはできません。 –