Почему setstate не обновляет значение в ReactJS?

#javascript #reactjs #react-hooks #state

Вопрос:

Я использую reactjs в своем приложении . Изначально currid_s имеет значение -1.. позже после нажатия кнопки он устанавливается на 2, но таймер не показывает обновленное значение в консоли. Почему? Вот код

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

export default function App() {
  const [currid_s, setcurrid_s] = React.useState(-1);
  const handless = () => {
    console.log("yess");
    setcurrid_s(2);
  };

  useEffect(() => {
    console.log(currid_s, "yes");
    getPosts();

    const interval = setInterval(() => {
      getPosts();
    }, 2000);

    return () => clearInterval(interval);
  }, []);

  // const all_pooo=()=>{
  //   console.log(curr,"dddd")
  // }
  const getPosts = async () => {
    console.log(currid_s);
  };
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <button onClick={handless}>gggg</button>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

 

Вот ссылка на песочницу кода
https://codesandbox.io/embed/beautiful-ardinghelli-dg1r4?file=/src/App.jsamp;codemirror=1

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

1. Функция обратного вызова интервала имеет замыкание по значению currid_s , которое действовало при установке интервала таймера. Вам нужно устанавливать новый интервал при currid_s каждом обновлении. Вы можете сделать это, добавив currid_s в массив зависимостей useEffect крючок.

2. @Yousaf, но как интервал влияет на значение currid_s?

3. Можете ли вы изменить код и поле @Yousaf, пожалуйста?

4. ДЕМОНСТРАЦИЯ

5. @Тушаршахи, что ты имеешь в виду? setInterval не изменяет свое значение; он просто вызывает функцию, getPosts т. Е. регистрирует значение currid_s .

Ответ №1:

Вы не можете получить новое значение состояния внутри setInterval , потому что вы храните старую версию getPosts внутри функции обратного вызова интервала.

Что происходит, так это при currid_s обновлении, повторной отправке компонента приложения и инициализации новой getPosts функции, содержащей новое значение. Однако setInterval функция обратного вызова сохраняет ссылку на старую getPosts функцию, содержащую старое значение. Эта старая getPosts функция будет печатать копию старого currid_s значения, которое было присвоено при монтаже компонента приложения. Javascript не поддерживает ссылки на примитивы, поэтому ваша старая getPosts функция не имеет нового значения.

Если вы хотите печатать свои currid_s обновления всякий раз, когда они обновляются, просто сделайте это:

 useEffect(() => {
  console.log(currid_s)
}, [currid_s])
 

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

1. У меня на сайте много крючков для реакции. Должен ли я добавить все это в зависимость?

Ответ №2:

Вы можете изменить currid_s значение с a useState() на a useRef() , чтобы его значение было доступно из закрытия, которое setInterval фиксирует обратный вызов:

 const { useRef, useEffect } = React;

function App() {
  const currid_s = useRef(-1);
  const handless = () => {
    currid_s.current = 2;
  };

  useEffect(() => {
    const getPosts = () => {
      console.log(currid_s.current);
    };

    getPosts();

    const interval = setInterval(() => {
      getPosts();
    }, 2000);

    return () => {
      clearInterval(interval);
    };
  }, []);
  
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <button onClick={handless}>Click me</button>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('root')); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>