SetInterval 未显示更新状态

ace*_*ndr 4 javascript setinterval reactjs react-hooks

在调用该setInterval函数之前,我已将状态设置为 true 。但是即使useEffect钩子是用状态的新值触发的,它也没有反映在setInterval函数中。

在此处输入图片说明 代码沙箱在这里:https : //jsfiddle.net/6e05tc2L/3/

let interval;
const Component = () => {
  React.useEffect(() => {
    console.log('State updated to', state);
  });
  const [state, setState] = React.useState(false);
  const on = () => {
    setState(true);
    interval = setInterval(() => {
      console.log(state);
    }, 1000);
    }
  const off = () => {
    setState(false);
    clearInterval(interval);
  }
  const toggle = () => state ? off() : on()

  return (<div>
    <button onClick={toggle}>Toggle State</button>
   </div>);
}

ReactDOM.render(
  <Component />,
  document.getElementById('container')
);
Run Code Online (Sandbox Code Playgroud)

一旦更新,它不应该使用更新的 state 值吗?

Muk*_*oni 12

您传递给 useEffect 的函数内的值在每次渲染时都会刷新,因为 useEffect 使用您传递给它的函数的新定义。

但是传递给 setInterval 的函数只定义了一次,它会关闭 state 的旧值。哪个还没有更新。

使用钩子关闭闭包很棘手,但要意识到 useEffect 为每个渲染创建一个新函数,因此每次函数关闭一个新的状态值时。

诀窍是在 useEffect 本身内部调用与 setInterval 相关的代码,这本身取决于 state 的变化值

React.useEffect(() => {
  if(state) {

    interval = setInterval(() => {
      console.log(state);
    }, 1000);
  } else {
    clearInterval(interval);
  }

}, [state]);
Run Code Online (Sandbox Code Playgroud)

或者,更好的是,使用 useInterval 钩子为您处理这些细节。

  • 闭包意味着关闭函数范围之外的值。这种差异并不是因为范围。这是因为一旦函数关闭一个值,它总是引用该变量。这就是 setInterval 回调发生的情况。它被定义一次并依附于状态的价值。但是您传递给 useEffect 的函数在每次渲染时都会被丢弃,并创建一个新函数,然后关闭变量中的最新值。 (3认同)

Ros*_*len 5

setInterval始终可以访问组件第一次渲染的值,因为传递给的函数setInterval会围绕该值关闭并且永远不会重新声明。您可以使用自定义挂钩来解决此问题:

function useInterval(callback, delay) {
  const savedCallback = useRef();

  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  useEffect(() => {
    function tick() {
      savedCallback.current();
    }

    let id = setInterval(tick, delay);
    return () => clearInterval(id);
  }, [delay]);
}
Run Code Online (Sandbox Code Playgroud)

该实现以及对 React Hooks 之间不匹配的全面解释setInterval来自React 贡献者之一 Dan Abramov 的Making setInterval Declarative with React Hooks 。