2016-08-20 6 views
3

は私が状態は不変であることを知っていて、これは、このredux reducerでObject.assignを使用する目的は何ですか?

//action = Object {type: "CREATE_COURSE", course: {title: algebra}} 

export default function courseReducer(state = [], action) { 
    switch(action.type) { 
     case 'CREATE_COURSE': 

      state.push(action.course) 
      return state; 

     default: 
      return state; 
    } 
} 

Pluralsight recommends this: 

export default function courseReducer(state = [], action) { 
    switch(action.type) { 
     case 'CREATE_COURSE': 
      return [...state, 
       Object.assign({}, action.course) 
      ]; 

     default: 
      return state; 
    } 
} 

プッシュとは、いや、変異状態ではありませんが、何がobject.assign使用していないと間違っていますか?これは間違っていますが、アプリがまだ動作しているようです。状態がまだ変更されていない場合は、新しい配列が返されます。

export default function courseReducer(state = [], action) { 
    switch(action.type) { 
     case 'CREATE_COURSE': 
      return [...state, 
       action.course 
      ]; 

     default: 
      return state; 
    } 
} 

CourseActions:

export function createCourse(course) { 
    return { type: 'CREATE_COURSE', course}; 
} 

CoursesPageコンポーネント:

import React, {PropTypes} from 'react'; 
import {connect} from 'react-redux'; 
import {bindActionCreators} from 'redux'; 
import * as courseActions from '../../actions/courseActions'; 

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

     this.state = { 
      course: { title: '' } 
     }; 

     this.onTitleChange = this.onTitleChange.bind(this); 
     this.onClickSave = this.onClickSave.bind(this); 
    } 

    onTitleChange(event) { 
     const course = this.state.course; // assign this.state.course to course 
     course.title = event.target.value; // reassign course.title to whatever was in input 
     this.setState({course: course}); // reassign state course to new course object with updated title 
    } 

    onClickSave() { 
     this.props.actions.createCourse(this.state.course); 
    } 

    courseRow(course, index) { 
     return <div key={index}>{course.title}</div>; 
    } 
    render() { 
     return (
       <div> 
        <h1>Courses</h1> 
        {this.props.courses.map(this.courseRow)} 
        <h2>Add Course</h2> 
        <input 
         type="text" 
         onChange={this.onTitleChange} 
         value={this.state.course.title} /> 
        <input 
         type="submit" 
         value="Save" 
         onClick={this.onClickSave} /> 
       </div> 
     ); 
    } 
} 

CoursesPage.propTypes = { 
    courses: PropTypes.array.isRequired, 
    actions: PropTypes.object.isRequired 
}; 

function mapStateToProps(state, ownProps) { 
    return { 
     courses: state.courses 
    }; 
} 

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

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

答えて

0

あなたがObject.assignを使用しない場合は、新しい配列の最後の要素はaction.courseするための基準となり、どんなものであれ、それは参考にされています。参照を渡すことはうまくいくかもしれませんが、何かがラインのどこかで突然変異し、問題を引き起こした場合、デバッグは難しくなります。転ばぬ先の杖。

0

あなただけの配列にaction.courseへの参照を置けば、this.props.coursesを使用し、あなたのすべてのコンポーネントがどの時点までの問題ではありません配列を共有内のすべてのオブジェクトcourse同じ参照を、表示されます意図的に/意図せずに一時的であってもそれらのいずれかを突然変異させる。

+0

2番目のコースを追加しようとすると、実際にこのエラーが発生します。 キャッチインバリアント違反:ディスパッチ間で状態が「courses.0.title」に検出されました。これにより、正しく動作しなくなる可能性があります。 action.courseは、コンポーネント内の同じ状態を直接参照しているため、入力に直接入力することで変更することができるため、Object.assignが必要な理由が考えられます。また、最初のコースが正しく追加されたにもかかわらず、実際に入力を入力すると、追加されたばかりのコースが変更されます。 OPにバックグラウンドコードを追加しました。 – yxu296

関連する問題