Javascript React-useState-为什么setTimeout函数没有最新状态值?
最近我在做React钩子,遇到了一个问题/疑问 下面是重现该问题的基本实现,在这里我只需点击按钮切换Javascript React-useState-为什么setTimeout函数没有最新状态值?,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,最近我在做React钩子,遇到了一个问题/疑问 下面是重现该问题的基本实现,在这里我只需点击按钮切换标志(状态)变量 const [flag, toggleFlag] = useState(false); const data = useRef(null); data.current = flag; const _onClick = () => { toggleFlag(!flag); // toggleFlag(!data.current); // wo
标志
(状态)变量
const [flag, toggleFlag] = useState(false);
const data = useRef(null);
data.current = flag;
const _onClick = () => {
toggleFlag(!flag);
// toggleFlag(!data.current); // working
setTimeout(() => {
toggleFlag(!flag); // does not have latest value, why ?
// toggleFlag(!data.current); // working
}, 2000);
};
return (
<div className="App">
<button onClick={_onClick}>{flag ? "true" : "false"}</button>
</div>
);
const[flag,toggleFlag]=useState(false);
const data=useRef(空);
data.current=标志;
const_onClick=()=>{
toggleFlag(!flag);
//toggleFlag(!data.current);//正在工作
设置超时(()=>{
toggleFlag(!flag);//没有最新值,为什么?
//toggleFlag(!data.current);//正在工作
}, 2000);
};
返回(
{标志?“真”:“假”}
);
我想出了一些其他的方法来解决这个问题,比如使用useRef或useReducer,但是这是正确的还是只有useState才能解决这个问题
另外,如果有人解释为什么我们在setTimeout中得到旧的状态值,那将非常有帮助
沙盒URL-这可以归结为闭包在JavaScript中的工作方式。赋予
setTimeout
的函数将从初始渲染中获取标志
变量,因为标志
没有变化
您可以将函数作为参数指定给toggleFlag
。此函数将获得正确的标志
值作为参数,此函数返回的内容将替换状态
示例
const{useState}=React;
函数App(){
const[flag,toggleFlag]=useState(false);
const_onClick=()=>{
toggleFlag(!flag);
设置超时(()=>{
toggleFlag(flag=>!flag)
}, 2000);
};
返回(
{标志?“真”:“假”}
);
}
render(,document.getElementById(“根”))代码>
赋予setTimeout
的函数将从\onClick
函数中获取标志
变量。每次渲染时都会创建\onClick
函数,并“存储”标志
变量在此渲染上获得的值
function App() {
const [flag, toggleFlag] = useState(false);
console.log("App thinks that flag is", flag);
const _onClick = () => {
console.log("_onClick thinks that flag is", flag);
toggleFlag(!flag);
setTimeout(() => {
console.log("setTimeout thinks that flag is", flag);
}, 100);
};
return (
<div className="App">
<button onClick={_onClick}>{flag ? "true" : "false"}</button>
</div>
);
}
\u onClick
是否在每次渲染时都会得到一个新的闭包和一个新的标志
值?@UjinT34是的,但是当第一次调用\u onClick
时,会创建超时,然后在稍后调用超时函数时,会在初始渲染的上下文中查找标志
,因此它会得到“旧的”关闭fotsetTimeout
何时创建?我认为它是在每次调用\u onClick
并获取\u onClick
捕获的标志时创建的,而不是原始的标志
变量。@UjinT34如果将App
视为一个函数,我认为这是有意义的,每次重新渲染都会导致对App
函数的新调用。对App
的第一次调用在对App
的第二次调用中没有“看到”变量。可能是我的“初始渲染”错误。对我来说,这听起来像是setTimeout
永远有flag=false
,就像第一次调用App
一样。请核对我的答案。
App thinks that flag is false
_onClick thinks that flag is false
App thinks that flag is true
setTimeout thinks that flag is false
_onClick thinks that flag is true
App thinks that flag is false
setTimeout thinks that flag is true