简体   繁体   English

尝试以间隔更改 React Hooks 中的 state

[英]Trying to change a state in React Hooks with Interval

I have a problem trying to change a state in react using setInterval .我在尝试使用setInterval更改 state 时遇到问题。 Why does the function "alert" always show a "null" message?为什么 function "alert" 总是显示 "null" 消息?

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

const Playlist = (props) => {

  const [test, setTest] = useState("");

  useEffect(() => {
    setInterval(load, 3000)
  }, []);

  const load = async () => {
    alert(test)
    setTest("TEST");
  }

  return (
    <div>
      {test}
    </div>
  )
}

export default Playlist

Issue:问题:

is callback passed into setInterval 's closure and it accesses the test variable in the first render.是回调传递到setInterval的闭包,它在第一次渲染中访问test变量。

Solution:解决方案:

You can clearInterval and setInterval as soon as there is any changes in your state只要您的 state 有任何变化,您就可以clearIntervalsetInterval

 const { useState, useEffect, useCallback } = React; const App = () => { const [test, setTest] = useState(""); useEffect(() => { const intrvl = setInterval(load, 3000); return () => clearInterval(intrvl); }, [test]); const load = () => { alert(test) setTest("TEST"); } return ( <div> {test} </div> ) } ReactDOM.render(<App />, document.getElementById('react-root'));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <div id="react-root"></div>

The problem is that useEffect captures the test from the first render which is equal to empty string.问题是useEffect从等于空字符串的第一个渲染中捕获test We never re-apply the effect so the closure in setInterval always references the test from the first render.我们从不重新应用效果,因此 setInterval 中的闭包始终引用第一次渲染的测试。

NOTE: setInterval does not describe a process in time — once you set the interval, you can't change anything about it except clearing it.注意: setInterval没有及时描述一个过程——一旦你设置了时间间隔,除了清除它之外,你不能改变它的任何东西。

When we pass an empty [] array of dependencies to useEffect, it only runs the useEffect on mount and cleanup on unmount of the component.当我们将一个空的[]依赖项数组传递给 useEffect 时,它只会在挂载时运行 useEffect 并在卸载组件时运行清理。

One way is to add test to the array of dependencies so anytime there is an update on test, the useEffect will be called.一种方法是将test添加到依赖项数组中,这样只要测试有更新,就会调用 useEffect。

 useEffect(() => {
   const intervalId = setInterval(load, 3000);
   return () => clearInterval(intervalId);
 }, [test]);

But since we are using the test inside useEffect, we can just remove the empty [] array of dependencies so the useEffect will be called every time we are setting the state (component is re-rendered) and the new setInterval will be created with accessing to the latest test state like below但是由于我们在 useEffect 中使用test ,我们可以删除空的[]依赖数组,因此每次设置 state 时都会调用 useEffect(重新渲染组件),并且新的 setInterval 将通过访问创建到最新的测试 state 如下

useEffect(() => {
   const intervalId = setInterval(load, 3000);
   return () => clearInterval(intervalId);
});

Another possible way is to update the state inside the interval's closure like另一种可能的方法是在区间的闭包内更新 state

useEffect(() => {
  const id = setInterval(() => {
    setTest("TEST");
  }, 3000);
  return () => clearInterval(id);
});

const App = () => {
  const [test, setTest] = useState("");

  useEffect(() => {
    const intervalId = setInterval(load, 3000);
    return () => clearInterval(intervalId);
  });

  const load = () => {
    alert(test)
    setTest("TEST");
  }

  return (
    <div>
      {test}
    </div>
  )
}

Example of interval with setting count so you can see the state change 设置计数的间隔示例,因此您可以看到 state 更改

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM