Не удается прочитать свойство состояния сравнения с нулем после изменения состояния

#reactjs #react-hooks

#reactjs #реагирующие крючки

Вопрос:

Я делаю игру в камень, ножницы, бумагу.

Я хочу увеличить выигрыши после того, как игрок выбрал свой вариант.

Я получаю сообщение об ошибке, как будто if оператор не знает о каком-либо значении.

Вот код:

Как выглядит состояние

 
 const [wins, setWins] = useState(0);
  const [playerSelect, setPlayerSelect] = useState(null);
  const [computerSelect, setComputerSelect] = useState(null);

  // in browser
  {id: 1, name:'rock'}
 

Функция выбора проигрывателя

   const handleSelection = choice => {
    const optionClicked = options.find(o => o.id === choice);

    setPlayerSelect(optionClicked);

    if (playerSelect.name === 'rock' amp;amp; computerSelect.name === 'scissors') {
      setWins(wins => wins   1);
    }
  };
 

Я попробовал добавить меры предосторожности, чтобы проверить, что состояние выбора игрока содержит значение, сначала не превалирующее. состояние выигрыша не увеличивается.

Пример:

  const handleSelection = choice => {
    const optionClicked = options.find(o => o.id === choice);

    setPlayerSelect(optionClicked);

    if (
      playerSelect amp;amp;
      playerSelect.name amp;amp;
      playerSelect.name === 'rock' amp;amp;
      computerSelect.name === 'scissors'
    ) {
      setWins(wins => wins   1);
    }
  };
 

Редактировать: я попробовал следующий код, и он работает только после второго щелчка.

 const checkWhoWins = () => {
      if (playerSelect.name === 'rock' amp;amp; computerSelect.name === 'scissors') {
        setWins(wins => wins   1);
      }
    };
    playerSelect amp;amp; checkWhoWins();
 

Комментарии:

1. setState является асинхронным, поэтому playerSelect является устаревшим состоянием в операторе if

2. Хорошо, я понимаю. Как тогда лучше всего это преодолеть? Добавление таймера или чего-то еще кажется немного неуклюжим.

Ответ №1:

если вы хотите выполнить действие после обновления состояния, вы должны использовать useEffect для этого и указать его зависимости в качестве второго аргумента:

 useEffect(() => {
      // you can use optional chaining to avoid triggering errors here
      if (playerSelect?.name === 'rock' amp;amp; computerSelect?.name === 'scissors') {
        setWins(wins => wins   1);
      }
}, [playerSelect, computerSelect]) 
   // playerSelect amp; computerSelect are the correct dependencies here