#reactjs #asynchronous #setstate
#reactjs #асинхронный #setstate
Вопрос:
Я пишу приложение Snake game для практики.
У меня есть функция changeDirection, которая задает соответствующее направление в состояние на основе щелчка стрелки:
changeDirection = event => {
const { direction } = this.state;
const keyPressed = event.keyCode;
if (keyPressed === keyCodes.LEFT_KEY amp;amp; direction !== "right") {
this.setState({ direction: "left" });
}
if (keyPressed === keyCodes.UP_KEY amp;amp; direction !== "down") {
this.setState({ direction: "up" });
}
if (keyPressed === keyCodes.RIGHT_KEY amp;amp; direction !== "left") {
this.setState({ direction: "right" });
}
if (keyPressed === keyCodes.DOWN_KEY amp;amp; direction !== "up") {
this.setState({ direction: "down" });
}
}
и это работает нормально, но проблема в другой функции.
Я обновляю положение головы змеи на основе состояния направления. и эта функция выполняется каждые 1 секунду (с setInterval), и при изменении направления голова змеи не меняет свое направление сразу. Она выполняет это на следующем шаге.
Я понимаю, что это потому, что состояние нового направления еще не установлено, когда snake перемещается в первый раз, но я не знаю, как это исправить.
вот репозиторий:https://github.com/Dito-Orkodashvili/snake
Комментарии:
1. Пожалуйста, включите весь соответствующий код. Невозможно сказать, что может быть неправильным из кода, который в данный момент находится в вашем вопросе.
2. Я добавил ссылку на репозиторий в исходное сообщение.
Ответ №1:
Вы можете использовать это.
this.setState({ direction: "down" },anotherFunction());
Вызовите вашу функцию в обратном вызове setState, она будет вызвана после обновления состояния.
ссылка:https://medium.learnreact.com/setstate-takes-a-callback-1f71ad5d2296
Комментарии:
1. Это кажется правильным.. Хотя, если его функция вызывается каждую секунду с помощью
setInterval
, код должен просто работать: 1)changeDirection()
изменяет состояние. 2) В конечном итоге,setInterval
вызовет функциюchangeHeadPosition()
, и это будет после (1) точки. Итак, я не знаю, почему у него проблема.. @Dito Возможно, вам следует показать и другую функцию2. Я знаю это, но проблема в том, что я вызываю эту ‘AnotherFunction’ в другом месте. p.s Я поместил ссылку на репозиторий целиком в исходное сообщение
3. Это должно быть
this.setState({ direction: "down" }, anotherFunction);
, если AnotherFunction не возвращает функцию
Ответ №2:
Вы обновляете состояние только направления. Это приводит к повторному отображению компонента. Затем вы обновляете состояние змеи, и компонент повторно визуализируется снова, а затем, когда вы видите, что заголовок обновлен.
Решением могло бы быть отключение функции moveSnake. Используйте moveSnake только для перемещения змеи после рендеринга компонента.
Создайте другую функцию для обновления состояния head и snake и вызовите ее из обработчика событий клавиатуры. Таким образом, компонент будет повторно отображать все изменения состояния одновременно.
Обновление состояния из setInterval также должно работать, например:
newDirection;
startGame = () => {
this.interval = setInterval(() => {
this.moveSnake();
}, 200);
};
changeDirection = event => {
const keyPressed = event.keyCode;
if (keyPressed === keyCodes.LEFT_KEY amp;amp; direction !== 'right') {
this.newDirection = 'left';
}
if (keyPressed === keyCodes.UP_KEY amp;amp; direction !== 'down') {
this.newDirection = 'up';
}
if (keyPressed === keyCodes.RIGHT_KEY amp;amp; direction !== 'left') {
this.newDirection = 'right';
}
if (keyPressed === keyCodes.DOWN_KEY amp;amp; direction !== 'up') {
this.newDirection = 'down';
}
};
moveSnake = () => {
/* do updates in the snake shape */
this.setState({
direction: this.newDirection,
snake: copyOfSnake
});
};
Комментарии:
1. Это именно то, что происходит, но я думаю, что ваше решение не подходит для моего случая. Потому что я обновляю положение головы snakes каждую секунду с использованием setInterval. Вот как движется змея. она сдвигает начало на одну ячейку вперед и удаляет хвост. итак, если я вызываю эту функцию только в событии нажатия клавиши, то змея не будет двигаться, пока я не нажму кнопку. поправьте меня, если я ошибаюсь.
2. Тогда решением могло бы быть не обновлять состояние напрямую из обработчика событий, а сохранить значение направления. Затем обновите состояние из setInterval, используя вашу переменную direction.