2016-05-14 6 views
0

После нажатия кнопки в моем приложении «Нативные приложения» я вызываю две функции: getSolutionListFromDatabase, которая устанавливает состояние компонента для включения этого списка решений, а затем updateDatabaseSolutionList, который добавляет элемент в этот список и отталкивает его обратно в Firebase. Однако, хотя состояние приложения должным образом обновляется в первой функции, во второй функции состояние регистрируется как неопределенное, а мои операторы журнала для этой функции вызывается перед некоторыми операторами в первой функции. Являются ли функции, работающие асинхронно по какой-либо причине, и является ли это особенностью React native? Если да, то как я могу предотвратить выполнение второй функции до тех пор, пока не будет установлено состояние? Благодарю.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 не гарантируется быть синхронными, так что вы не можете полагаться на государство обновляется сразу после него.

См https://facebook.github.io/react/docs/component-api.html

setState() не сразу мутировать this.state но создает отложенный переход состояния. Доступ к this.state после вызова этого метода может потенциально вернуть существующее значение.

Нет гарантии синхронной работы звонков на setState, и звонки могут быть отправлены для повышения производительности.

API-интерфейс действительно обеспечивает функцию обратного вызова для того, когда государство фактически обновляется, хотя:

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

В качестве альтернативы, вы можете скоротать solutionList непосредственно к следующей функции, а затем установить их как в состоянии при в то же время, что кажется лучшим вариантом.

+0

Спасибо за советы. Когда я пытаюсь передать решениеList непосредственно следующей функции, просто вернув snap.val(), функция возвращается как неопределенная, даже если она регистрирует правильные значения для snap.val внутри функции. Какие-нибудь идеи, что может происходить здесь? – user3802348