2016-05-14 10 views
0

反応ネイティブアプリのボタンをクリックすると、このソリューションリストを含むようにコンポーネントの状態を設定するgetSolutionListFromDatabaseと、このリストに要素を追加してFirebaseに戻すupdateDatabaseSolutionListという2つの関数が呼び出されます。しかし、アプリケーションの状態は最初の関数内で正しく更新されていますが、2番目の関数では状態は未定義として記録されており、その関数のログ文は最初の関数のいくつかの文の前に呼び出されています。何らかの理由で関数が非同期で動作しているのですが、これはReactネイティブの機能ですか?もしそうなら、どのようにして状態が設定されるまで第2の関数が実行されるのを防ぐことができますか?ありがとう。React-nativeは、関数が非同期に実行されるのを防ぎますか?

onSubmitPressed: function() { 
    if (this.checkSolution) { 
     this.getSolutionListFromDatabase(); 
     this.updateDatabaseSolutionList(); 
     Alert.alert(
      'Correct!', 
      "Woohoo!" 
     ); 
    } 
}, 

getSolutionListFromDatabase: function() { 
    var thisItemRef = itemsListRef.child(this.state.itemID); 
    thisItemRef.once('value', (snap) => { 
     var solutionList = snap.val(); 
     this.setState({ 
      solutionList: solutionList 
     }); 
     console.log('solution is set as' + this.state.solutionList); 
    }); 
}, 

updateDatabaseSolutionList: function() { 
    var newSolutionList = []; 
    console.log('solutionList undefined here' + this.state.solutionList); 

    if (this.state.solutionList) { 
     newSolutionList = this.state.solutionList; 
     newSolutionList.push(this.props.itemID); 
    } 

    //then push new list to Firebase 
}, 

答えて

5

ロジックは常にanswer to your previous questionと同じです。あなたは、イベント間の依存関係を持っている場合は、最初のコールバックへの呼び出しを移動する必要があります。

onSubmitPressed: function() { 
    if (this.checkSolution) { 
     this.getSolutionListFromDatabase(); 
    } 
}, 

getSolutionListFromDatabase: function() { 
    var thisItemRef = itemsListRef.child(this.state.itemID); 
    thisItemRef.once('value', (snap) => { 
     var solutionList = snap.val(); 
     this.setState({ 
      solutionList: solutionList 
     }); 
     console.log('solution is set as' + this.state.solutionList); 
     this.updateDatabaseSolutionList(); 
    }); 
}, 

updateDatabaseSolutionList: function() { 
    var newSolutionList = []; 
    console.log('solutionList undefined here' + this.state.solutionList); 

    if (this.state.solutionList) { 
     newSolutionList = this.state.solutionList; 
     newSolutionList.push(this.props.itemID); 
    } 

    Alert.alert(
     'Correct!', 
     "Woohoo!" 
    ); 
    //then push new list to Firebase 
}, 

流れのこのタイプは、関数に(すなわちsolutionList)前提条件を渡す場合は、自分自身のために従うことが非常に簡単になります代わりに、フィールド/プロパティを使用しての、それを必要とします。

onSubmitPressed: function() { 
    if (this.checkSolution) { 
     this.getSolutionListFromDatabase(); 
    } 
}, 

getSolutionListFromDatabase: function() { 
    var thisItemRef = itemsListRef.child(this.state.itemID); 
    thisItemRef.once('value', (snap) => { 
     var solutionList = snap.val(); 
     this.updateDatabaseSolutionList(solutionList); 
    }); 
}, 

updateDatabaseSolutionList: function(solutionList) { 
    solutionList.push(this.props.itemID); 

    Alert.alert(
     'Correct!', 
     "Woohoo!" 
    ); 
    //then push new list to Firebase 
}, 

しかし、より良い代わりに単に最初の配列全体をダウンロードして、単一の新しいアイテムでそれを送り返すの、push()にまっすぐFirebaseに新しい値になりますそれに追加されました:

onSubmitPressed: function() { 
    if (this.checkSolution) { 
     itemsListRef.child(this.state.itemID).push(...); 
    } 
}, 
2

setStateは、同期であることが保証されていないので、あなたはすぐにそれの後に更新されている状態に依存することはできません。

はすぐにthis.state変化させません

setState()https://facebook.github.io/react/docs/component-api.htmlを参照してくださいが、保留状態遷移を作成します。このメソッドを呼び出した後this.stateにアクセスすると、潜在的に既存の値が返される可能性があります。

setStateへのコールの同期動作の保証はなく、パフォーマンスの向上のためにコールをバッチ処理することができます。

void setState(
    function|object nextState, 
    [function callback] 
) 

を別の方法として、あなたは次の関数に直接solutionListを渡し、その後で両方の状態でそれらを設定することができます:APIは状態が実際にかかわらず、更新されたときのコールバックを提供してい

同じ時間、より良い選択肢のように思える。

+0

ヒントをありがとう。 snap.val()を返すだけで、次の関数に直接solutionListを渡そうとすると、関数内のsnap.valに正しい値を記録していても、関数は未定義として返します。ここで何が起きているのでしょうか? – user3802348

関連する問題