2017-08-05 19 views
0

私は反応を使って要素のリストを作成しようとしています、そして、単一の要素がクリックされたときにこのリストの親の状態を更新しようとしています。更新grandchildのonClickから親の状態に反応します

全体的な容器はApp.jsx(祖父母)

class App extends Component { 
    constructor(props) { 
    super(props); 

    this.state = { 
     selectedClass: null, 
     query: "cs 2110" 
    } 

    this.handleSelectClass.bind(this); 
    } 

    handleSelectClass(classId) { 
    console.log(classId); 

    //get the id of the course and get full course details 
    Meteor.call('getCourseById', classId, function(error, result) { 
     if (!error) { 
     console.log(this.state); 
     this.setState({selectedClass: result, query: ""}, function() { 
      console.log(this.state.selectedClass); 
      console.log(this.state.query); 
     }); 
     } else { 
     console.log(error) 
     } 
    }); 
    } 

    //check if a class is selected, and show a coursecard only when one is. 
    renderCourseCard() { 
    var toShow = <div />; //empty div 
    if (this.state.selectedClass != null) { 
     toShow = <CourseCard course={this.state.selectedClass}/>; 
    } 
    return toShow; 
    } 

    render() { 
    return (
     <div className="container"> 
     <header> 
      <h1>Todo List</h1> 
     </header> 
     <div className='row'> 
      <input /> 
      <Results query={this.state.query} clickFunc={this.handleSelectClass}/> 
     </div> 
     <div className='row'> 
      <div className="col-md-6"> 
      {this.renderCourseCard()} 
      </div> 
      <div className="col-md-6 panel-container fix-contain"> 
      <Form courseId="jglf" /> 
      </div> 
     </div> 
     </div> 
    ); 
    } 
} 

親コンテナがResults.jsx

export class Results extends Component { 
    constructor(props) { 
    super(props); 
    } 

    renderCourses() { 
    if (this.props.query != "") { 
     return this.props.allCourses.map((course) => (
     //create a new class "button" that will set the selected class to this class when it is clicked. 
     <Course key={course._id} info={course} handler={this.props.clickFunc}/> 
    )); 
    } else { 
     return <div />; 
    } 
    } 

    render() { 
    return (
     <ul> 
     {this.renderCourses()} 
     </ul> 
    ); 
    } 
} 

であり、コースリスト項目が孫成分

export default class Course extends Component { 
    render() { 
    var classId = this.props.info._id; 
    return (
     <li id={classId} onClick={() => this.props.handler(classId)}>{this.props.info.classFull}</li> 
    ); 
    } 
} 
あります

ここに私の提案に従いましたReactjs - How to pass values from child component to grand-parent component?コールバックfunctioを渡すnが、コールバックはまだ祖父母の状態を認識しません。 classIdが正しいにもかかわらず、App.jsxのconsole.log(this.state)がundefinedを返し、「getCourseById 'を呼び出す結果の配信で例外が発生しました:TypeError:this.setStateが関数ではありません」

これはバインディングの問題ですか?私はコースなしでこれを独自のコンポーネントとして試してみましたが、同じ問題があります。

答えて

0

すばやくコードを見てください。私はその問題がここにあるのを見ることができます。あなたの関数をコンポーネントに束縛していても、それ自身の関数スコープ内の結果をスコープする流星の呼び出しを使用しています。つまり、this.setStateにアクセスすることはできません。太い矢印の機能を使ってこの問題を回避することができますが、ES6を使用していることを確認する必要があります。

Meteor.call('getCourseById', classId, function(error, result) => { 
    if (!error) { 
    console.log(this.state); 
    this.setState({selectedClass: result, query: ""}, function() { 
     console.log(this.state.selectedClass); 
     console.log(this.state.query); 
    }); 
    } else { 
    console.log(error) 
    } 
}); 

Meteor.call('getCourseById', classId, (error, result) => { 
    if (!error) { 
    console.log(this.state); 
    this.setState({selectedClass: result, query: ""},() => { 
     console.log(this.state.selectedClass); 
     console.log(this.state.query); 
    }); 
    } else { 
    console.log(error) 
    } 
}); 

TOまた、あなたのコンポーネントに間違ってあなたの関数をバインドさしました。

this.handleClassSubmit = this.handleClassSubmit.bind(this); 
+0

これらの変更を試みましたが、ログに未定義のthis.stateが残っています(エラーはありませんが、流星のデバッグでは「メッセージなし」と表示されています)。私は最新のMeteorビルドを使用していますので、es6を実行していると思います。es5-shimと[email protected]パッケージがインストールされています。 –

+0

ちょうどあなたが正しくコンポーネントにあなたの関数をバインドしているのを見た 'this.handleSelectClass = this.handleSelectClass.bind(これ);' – Win

+0

ああ私はそれを逃した - ありがとう、それは固定! –

関連する問題