ReactJS: Почему разные значения из одного состояния? - PullRequest
5 голосов
/ 01 ноября 2019

Итак, я вхожу в Reactjs с очень базовым компонентом. Я выхожу из одного и того же состояния из разных функций, но я вижу разные значения.

import React, { useState, useEffect, useRef } from "react";

const Test = props => {
  const [count, setCount] = useState(0);

  useEffect(()=>{
      setInterval(() => {
        console.log("count in interval is:", count);
      }, 1000);
  },[props]);

  function btnClick() {
    const newCount = count + 1;
    setCount(newCount);
    console.log("count changed to: ", newCount);
  }
  return (
    <div>
      count is {count}
      <br></br>
      <button onClick={btnClick}>+</button>
    </div>
  );
};

export default Test;

Вывод после нескольких нажатий и ожидания, журнал:

Test.js:8 count in interval is: 0
Test.js:15 count changed to:  1
Test.js:15 count changed to:  2
Test.js:15 count changed to:  3
Test.js:15 count changed to:  4
(8 rows) Test.js:8 count in interval is: 0

Я ожидаю, что «количество» будет одинаковым в обеих функциях. Кто-нибудь может объяснить это?

Большое спасибо.

Ответы [ 2 ]

2 голосов
/ 01 ноября 2019

Test имеет только одну функцию setInterval, где count всегда 0. Так как он создается только во время начального рендеринга.

В нем никогда не было создано другого setInterval, поскольку эффект никогда не срабатывал с [props] в качестве зависимости.

Для изменения количества setInterval при каждом повторном рендеринге:

  • Удаление зависимости
  • Возвращение функции очистки внутри эффекта
useEffect(
  () => {
    const t = setInterval(() => {
      console.log("count in interval is:", count);
    }, 1000);

    return () => clearInterval(t); // cleanup on every re-render
  }
  // no dependency: effect runs on every re-render
);

Но приведенный выше код будет иметь предупреждение:

" отсутствует count зависимость "

Так что просто добавьте count как зависимость к , запустите эффект только при изменении count.

useEffect(
  () => {
    const t = setInterval(() => {
      console.log("count in interval is:", count);
    }, 1000);

    return () => clearInterval(t); // cleanup "old" setInterval
  }
  , [count] // ony run effect every time count changes
);
0 голосов
/ 01 ноября 2019

Значение count не меняется, это ожидаемое поведение, хотя и не очевидное.

Видите, вы даже объявляете count как const count, оно неизменное. Вместо этого происходит то, что во время первого рендеринга count получает присвоенное значение 0. Значение count никогда не изменяется, вместо этого происходит то, что компонент Test вызывается каждый раз, когда вы меняете состояние, а функция useState присваивает различные значения константе count, которая каждый раз является новой константой.

Таким образом, во время первого рендеринга значение const count захватывается замыканием внутри вашей функции, которая вызывается setInterval, и значение остается 0 навсегда.

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