Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript SetInterval未显示更新状态_Javascript_Reactjs_Setinterval_React Hooks - Fatal编程技术网

Javascript SetInterval未显示更新状态

Javascript SetInterval未显示更新状态,javascript,reactjs,setinterval,react-hooks,Javascript,Reactjs,Setinterval,React Hooks,在调用setInterval函数之前,我已将状态设置为true。但是,即使使用状态的新值触发useffect钩子,它也不会反映在setInterval函数中 代码沙箱: let间隔; 常量组件=()=>{ React.useffect(()=>{ console.log('状态更新为',状态); }); const[state,setState]=React.useState(false); const on=()=>{ 设置状态(真); 间隔=设置间隔(()=>{ console.log(状

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

代码沙箱:

let间隔;
常量组件=()=>{
React.useffect(()=>{
console.log('状态更新为',状态);
});
const[state,setState]=React.useState(false);
const on=()=>{
设置状态(真);
间隔=设置间隔(()=>{
console.log(状态);
}, 1000);
}
常数off=()=>{
设置状态(假);
间隔时间;
}
常量切换=()=>状态?关闭():打开()
返回(
切换状态
);
}
ReactDOM.render(
,
document.getElementById('容器')
);

它不应该在更新后使用更新的state值吗?

如果您想在状态更改时重新加载组件,您应该像这样创建useEffect

React.useEffect(() => {
    console.log('State updated to', state);
}, [state]);
您创建组件的方式与
componentDidMount()
相同,第二个参数是数组,它与
componentdiddupdate()
的依赖项类似。因此,只要状态发生更改,组件就会重新渲染

要解决setTimeout的无限调用,可以在创建函数的地方执行此操作

React.useCallback(() => {
    setInterval(() => {
        console.log(state);
    }, 1000);
})

有了这个React,您就会知道您只想创建这个函数一次。

我不是ReactJS专家,但我想您正在记录的
状态没有刷新,因为它声明了一次,而且从未刷新过。如果
React.useState(false)
是提供状态的方法,则应在区间函数中使用它

下面是我试图解释的一个例子:

const object={value:false}
const notrefresh=object.value//我们在这里复制值
常量间隔=设置间隔(()=>{
const refreshed=object.value//这里我们使用引用来复制最新的值
日志(“刷新”,刷新)
log(“notrefresh”,notrefresh)
}, 500)
setTimeout(()=>object.value=true,1600)

setTimeout(()=>clearInterval(interval),2600)
传递给useEffect的函数中的值在每次渲染时都会刷新,因为useEffect使用传递给它的函数的新定义

但是传递给setInterval的函数只定义了一次,它会在旧的state值上关闭。尚未更新

使用钩子进行闭包是很棘手的,但要认识到的是,useEffect会为每个渲染创建一个新函数,因此每次函数在新状态值上关闭时都会创建一个新函数

然后,诀窍是在useEffect本身中调用与setInterval相关的代码,这本身取决于状态值的变化

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

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

}, [state]);

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

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

函数useInterval(回调、延迟){
const savedCallback=useRef();
useffect(()=>{
savedCallback.current=回调;
});
useffect(()=>{
函数tick(){
savedCallback.current();
}
让id=设置间隔(滴答声,延迟);
return()=>clearInterval(id);
},[延迟];
}

React贡献者之一Dan Abramov提供了React钩子和setInterval之间不匹配的实现和彻底解释。

如果我们使用局部变量,那么即使变量不在函数范围内,它也会使用变量的更新值。钩住状态的闭包与变量的闭包有何不同?闭包意味着在函数范围之外的值上闭包。这种差异不是因为范围。这是因为一旦函数关闭某个值,它总是引用该变量。这就是setInterval回调发生的情况。它被定义了一次,并依附于状态的任何值。但是传递给useEffect的函数在每次渲染时都会被丢弃,并创建一个新的函数,然后关闭变量中的最新值。接受这个答案是因为它显示了解决此问题的简单方法。我所说的变量是假设我们有一个单独的全局声明的计数器变量,如果我们使用setInterval来增加它,那么它会增加它,而不需要在useffect钩子下定义它,但这是全局的。并在模块退出或程序退出之前一直在作用域中<代码>状态
在您的情况下,在渲染功能运行完成后,请退出范围。只有在该函数中定义的函数才能通过闭包访问该变量。这很有意义!我没想到会这样!我对这个问题有了一些“结论!”:)投票支持丹的文章!但是它并没有解释为什么会发生这种情况,而是提供了一个很好的解决方法。传递给
setInterval
的函数在调用
on
时只创建了一次,并且在创建时关闭了
state
的值。Future呈现调用
React.useState
并再次“查看”一个新的
状态
,但当调用
on
时创建的函数基本上停留在过去:它在创建时关闭了
状态
,并且永远不会获得
状态
的新值。因此,如果您查看Abramov的
useInterval
,它在每次渲染时调用
useffect
,并使用新版本的回调更新ref的
.current
,该回调在该渲染调用的
state
值上关闭。传递给本机
setInterval
的函数从未更改,但该函数所做的只是调用另一个函数,该函数的引用实际上在每次重新调用时都在更新
React.useEffect(() => {
  if(state) {

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

}, [state]);