useState не устанавливается в React - PullRequest
3 голосов
/ 26 июня 2019

Я пытаюсь заставить useState работать, когда пользователь нажимает стрелки вверх или вниз и по какой-то причине состояние не обновляется.

Даже если я установил Timeout, чтобы увидеть, обновляется ли index , все еще нет.Полностью смущен здесь с этим.

import React, { useEffect, useState } from 'react';

const Wrapper = ({ children }) => {
  const [index, setIndex] = useState(-1);

  useEffect(() => {
    document.addEventListener('keydown', handler);
    return () => {
      document.removeEventListener('keydown', handler);
    };
  }, []);

  const handler = (event) => {
    if (event.key === 'ArrowDown') {
      setIndex(index + 1);
      console.log('index = ', index);
    }
  };

  return (
    <div>
      {children}
    </div>
  );
};

export default Wrapper;

Ответы [ 2 ]

4 голосов
/ 26 июня 2019

Из-за асинхронной природы setState вы должны регистрировать предыдущее состояние.

setIndex(prev => {
  console.log("prev = ", prev);
  return prev + 1;
});

Edit Q-56778259-LogPrevState

0 голосов
/ 26 июня 2019

Подсказка в const [index... - она ​​никогда не изменится. Используйте функциональную форму setState:

const handler = (event) => {
  if (event.key === 'ArrowDown') {
    setIndex(oldIndex => oldIndex + 1)
  }
}

Это потому, что index во время первого рендеринга будет -1, никогда не меняется даже в замыкании внутри функции handle. Во время нового рендеринга будет создана новая функция handle с другой константой index, но эта функция будет проигнорирована, поскольку второй аргумент useEffect(fn, []) гарантирует, что fn будет выполняться ТОЛЬКО во время первого рендеринга.

Подробнее см. https://overreacted.io/a-complete-guide-to-useeffect/.

...