Я сделал простую игру камень-ножницы-бумага. Во время onclick
я вызываю функцию для добавления числа и изменения состояния. Затем внутри этой функции я вызываю еще 2 функции: одна выбирает случайное число от 1 до 3, преобразует его в камень/ножницы/бумагу и присваивает его состоянию, а затем другая функция определяет, кто выиграл:
addToInput = val =>{
this.setState({
input:val
});
this.picknum();
this.pickwin();
}
https://codepen.io/russiandobby/pen/xeRYzw?editors=0002
Сначала я думал, что picknum
и pickwin
будут выполняться одновременно, однако, даже если я попытаюсь вызвать pickwin
внутри picknum
, это все равно не сработает.
Кажется, что когда pickwin
выполняется, он смотрит на старое состояние, а не на состояние, которое изменяется picknum
.
Как я могу решить эту проблему?
покажи свой забавный код picknum() и pickwind()..
Это асинхронный механизм javascript
this.setState({
input:val
});
если вы хотите синхронизироваться. Давайте использовать async/await. вот мой код:
addToInput = async val =>{
// console.info('add function');
await this.setState({
input:val
});
await this.picknum();
await this.pickwin();
}
Давай попробуй!
Это правда, что setState является (или может быть) асинхронным, но он не возвращает промис, поэтому ожидание не поможет.
Кажется, проблема исправлена, если я что-то упустил
Ожидание не-обещания только задержит код до следующей микрозадачи и не гарантирует, что он дождется того, чего, по вашему мнению, вы ждете. Если добавление await решило проблему, то вам повезло. Это неправильный способ решить проблему такого рода.
тогда как можно решить эту проблему. я думаю, если бы все было показано в одной функции и использовалось бы только одно setstate, это бы исправило это, но есть ли другой способ это исправить
setState является асинхронным (или, по крайней мере, может быть), поэтому нет гарантии, что состояние было обновлено, когда вы переходите к следующим строкам кода. Если вам нужно что-то запустить после установки состояния, либо поместите его в Обработчик жизненного цикла componentDidUpdate или передать обратный вызов в setState в качестве второго параметра.
Например, вы можете пропустить pickWin в своей функции addToInput и вместо этого иметь функцию componentDidUpdate, подобную этой:
componentDidUpdate(prevProps, prevState) {
this.pickWin();
}
Тем не менее, вместо того, чтобы устанавливать состояние, затем ждать его обновления, а затем снова устанавливать состояние, я бы рекомендовал вам реорганизовать свой код, чтобы просто вызвать setState один раз. Если вы вызываете его несколько раз, у вас есть возможность вызвать несколько рендеров, но похоже, что все они предназначены для того, чтобы быть частью одной и той же операции. Возможно, обновите свои функции pickNum и pickWin, чтобы они возвращали значение, а не устанавливали само состояние, а затем вызывайте setState один раз с результатами.
picknum () {
let aipick = ["rock","paper","scisors"];
let temp = Math.floor(Math.random() * 3) + 0 ;
return aipick[temp]
}
pickWin(userChoice, aiChoice) {
if (userChoice === 'rock' && aiChoice == 'scisors') {
return 'USER WINS';
}
// etc
}
addToInput = val => {
let aiChoice = pickNum();
let winner = pickWin(val, aiNum);
this.setState({
aiChoice: aiChoice,
whowon: winner,
input: val,
})
}
Спасибо, я попытался сделать обратный вызов, и теперь он работает.
Итак, кажется, что обратные вызовы могут быть одним из решений, поэтому я пытался сделать это
picknum (){
let aipick=["rock","paper","scisors"];
let temp =Math.floor(Math.random() * 3) + 0 ;
this.setState({
aichoice:aipick[temp]
},function(){
this.pickwin();
}
)
}
////////////
addToInput = val =>{
// console.info('add function');
this.setState({
input:val
},function(){
this.picknum();
}
);
}
кажется, работает сейчас.
Возможный дубликат Почему вызов метода setState реакции не изменяет состояние немедленно?