2016-12-04 6 views
1

以下のリアクションコードは、初めてFirebaseからデータスナップショットを取得します。 this.state.termは、Firebaseデータベース内のノードのインデックスを指します。私のhandleChoice関数はthis.setStateですが、新しいデータスナップショットを取得するためにこのコンポーネントを再描画しているようではありません。リアクションコンポーネントがFirebaseデータを取得するために再レンダリングされない

this.state.termの値はcomponentDidMountの下で変更されません。しかし、私がコンソールでそれをレンダリングでログアウトすると、それが実行されます。

import React, { Component } from 'react'; 
import NavBar from './navbar.js'; 
import TermInfo from './termInfo.js'; 
import * as firebase from 'firebase'; 
import './App.css'; 

class App extends Component { 

    constructor(){ 
    super(); 

    this.state = { 
     term: 66,   //sample term to load first 
     examples: [1,2,3], 
     dataNode: {}, 
    } 
    } 

componentDidMount(){ 
     let rootRef = firebase.database().ref('vocab/').child(this.state.term); 

    rootRef.on('value', snap => { 
     this.setState({ 
      dataNode: snap.val(), 
      examples: Object.assign([], snap.val().examples) 
     }); 
     }); 
    } 


    _handleChoice(theChosenOne){ 
     this.setState({ 
     term: theChosenOne 
     }); 
    } 

    render() { 
    console.log(this.state.term); //this gives me the right index 
    return (
     <div className="App"> 
     <div className="App-header"> 
     <NavBar choose={this._handleChoice.bind(this)}/> 
     </div> 
     <div className='container'> 
     <div className="jumbotron"><TermInfo node={this.state.dataNode} examples={this.state.examples}/> 
     <p className="App-intro"> 
      Enter a vocabulary term to search for and add examples! 
     </p></div> 
     </div></div> 
    ); 
    } 
} 

export default App; 

なぜデータを再レンダリングせずに取り込みませんか?

答えて

2

重要な点はcomponentDidMountであり、Reactコンポーネントのライフサイクルで一度だけ実行され、初期レンダリングの直後に表示されます。もう一度。

official Docから引用:

componentDidMount()は、コンポーネントが が装着された直後に呼び出されます。 DOMノードを必要とする初期化はここに行かなければなりません。 がリモートエンドポイントからデータをロードする必要がある場合、これは がネットワーク要求をインスタンス化するのに適しています。このメソッドで状態を設定すると、 が再レンダリングをトリガーします。


handleChoiceは、いくつかのイベント(一部のユーザ対話の結果)に基づいてトリガされるように思えます。これは、それぞれの呼び出しでAPIコールをhandleChoiceに呼び出す必要があることを意味します。

また、選択したインデックスを維持するための状態は必要ありません。代わりにhandleChoiceで受け取ったインデックスを直接使用して、firebaseのスナップを撮りましょう。私のマウントとレンダリングの区別を教えるため

class App extends Component { 

    constructor(){ 
    super(); 

    this.state = { 
     examples: [1, 2, 3], 
     dataNode: {}, 
    }; 
    } 

    componentDidMount() { 
    this.getData(66); // sample term to load first 
    } 

    getData(index) { 
    const rootRef = firebase.database().ref('vocab/').child(index); 

    rootRef.on('value', snap => { 
     this.setState({ 
     dataNode: snap.val(), 
     examples: Object.assign([], snap.val().examples) 
     }); 
    }); 
    } 

    _handleChoice(theChosenOne) { 
    this.getData(theChosenOne); 
    } 

    render() { 
    console.log(this.state.term); //this gives me the right index 
    return (
     <div className="App"> 
     <div className="App-header"> 
      <NavBar choose={this._handleChoice.bind(this)} /> 
     </div> 
     <div className='container'> 
      <div className="jumbotron"> 
      <TermInfo node={this.state.dataNode} examples={this.state.examples}/> 
      <p className="App-intro"> 
       Enter a vocabulary term to search for and add examples! 
      </p> 
      </div> 
     </div> 
     </div> 
    ); 
    } 
} 
+0

ありがとう:

だから、私たちのコンポーネントは次のようになります。私は全然ノブです。これは魅力的に機能しました。 –

0

状態が変更された後でcomponentDidMountが呼び出されることはありません(_handleChoice)ので、生成されたhtmlの変更は表示されません。あなたは常に最新のthis.state.termを取得したいので、componentWillUpdateの状態とfirebase関連の設定を代わりに設定してみてください。 react's docsを参照してください。