Проблема с хуками useInterval и реагировать - бесконечный цикл - PullRequest
0 голосов
/ 25 апреля 2020

У меня есть компонент игральных костей, и я хочу, чтобы он выплевывал случайные значения n раз, и после этого показывает значение c, и это должно происходить каждый раз, когда реквизит обновляется. поэтому я использовал setInterval в следующем коде:

  //iter - keep count on how many times we rendered a value
  const [iter, setIter] = useState(0);

  //keep the intervalId given throughout the renderes
  const [intervalId, setIntervalId] = useState(undefined);

  //check each render(iter update) if iter has reached 0, to clear the interval
  useEffect(() => {
    if (iter <= 0) {
      clearInterval(intervalId);
    }
  }, [iter]);

  //if the props updated, call roll dice
  useEffect(() => {
    rollDice();
  }, [props]);

  const rollDice = () => {
    const interval = setInterval(() => {
      //reduce iter every 100ms
      setIter((prev) => prev - 1);
    }, 100);

    //run this interval 10 times
    setIter(10);
    setIntervalId(interval);
  };

Это то, что возвращает компонент:

 {props.values.map((val, i) => (
    <FontAwesomeIcon
      key={i}
      //randomize icons
      icon={dice[iter ? Math.floor(Math.random() * 5) : val - 1]}
      size={props.size || "4x"}
      color={props.color || "white"}
    />
  ))}

Но по какой-то причине я получаю бесконечное l oop, первый useEffect продолжает стрелять. Почему это происходит и как я могу избежать такого рода ошибок в будущем?

Спасибо.

1 Ответ

1 голос
/ 25 апреля 2020

Я думаю, что проблема в том, что вы используете состояние для хранения локальных переменных. Вы вызываете setIter для обновления iter, но setIter является асинхронным. Таким образом, он не будет обновляться немедленно, что означает, что iter может пропускать 0 и go в отрицательные числа, которые будут бесконечными, если вы просто проверите, если iter отличается от 0. Но, конечно, это будет работать (вроде) если вы проверите, что iter больше 0.

Вы должны заменить свое состояние iter на ref:

const iter = useRef(0);

Затем вы можете обновить его, используя его текущее значение:

iter.current = 10;
iter.current--;

Тогда ваш код значка будет:

icon={dice[iter.current ? Math.floor(Math.random() * 5) : val - 1]}

Аналогично, интервал ID должен храниться не в состоянии, а в ссылке:

const intervalId = useRef();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...