Fre*_*eon 10 settimeout reactjs redux react-redux
这很简单。我正在使用 Redux 来管理我的状态
setTimeout
我在函数中有一个函数useEffect
。
其setTimeout
超时值为50000
ms。
50000ms
该setTimeout
函数检查是否已收到 api 调用响应后。
如果尚未收到响应,setTimeout
函数应重新启动 api 调用,因为调用将被视为超时。
之后50000ms
,即使已收到响应,setTimeout 处理程序仍会重新启动 api 调用。
我尝试记录状态的输出,然后它返回缓存的状态,即使状态已传递到函数的依赖项数组useEffect
并且应该已更新
进行 api 调用后,testDetails.isUpdatingTestDetails
状态设置为false
我尝试了几种逻辑,但没有一个有效
useEffect(() => {
//Notice how i check if the testDetails is being updated before initiating the setTimeout callback
if (testDetails.isUpdatingTestDetails === true) {
setTimeout(() => {
// Inside the settimeout function the same check is also done.
// even though before 50 seconds the response is being received , the function logs the text simulating the reinitiation of an api call
return testDetails.isUpdatingTestDetails === true &&
console.log("After 50 Seconds You Need To Refetch This Data")
}, 50000);
}
}, [testDetails.isUpdatingTestDetails, testDetails])
Run Code Online (Sandbox Code Playgroud)
useEffect(() => {
setTimeout(() => {
return testDetails.isUpdatingTestDetails === true &&
console.log("After 50 Seconds You Need To Refetch This Data")
}, 50000);
}, [testDetails.isUpdatingTestDetails, testDetails])
Run Code Online (Sandbox Code Playgroud)
我上面应用的逻辑都不起作用。
Ram*_*ddy 21
状态过时的原因:
的useEffect
回调形成了当时状态的闭包。因此,当执行超时回调时,即使状态同时更新,它也只能使用旧状态。
一旦状态发生变化,useEffect
将再次运行(因为状态是依赖项)并启动新的超时。
第二次超时将使用新状态,因为闭包是用新状态形成的。如果状态第三次更改,此超时也容易受到陈旧状态问题的影响。
解决方案:
当状态改变时,你可以清除之前的超时时间。这样,除非是最新的,否则不会执行超时回调。
export default function App() {
const [state, setState] = useState(true);
useEffect(() => {
const timeout = setTimeout(() => {
console.log(state);
}, 5000);
return () => {
// clears timeout before running the new effect
clearTimeout(timeout);
};
}, [state]);
return (
<div className="App">
<h1>State: {state.toString()}</h1>
<button onClick={() => setState(false)}>update</button>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
export default function App() {
const [state, setState] = useState(true);
useEffect(() => {
const timeout = setTimeout(() => {
console.log(state);
}, 5000);
return () => {
// clears timeout before running the new effect
clearTimeout(timeout);
};
}, [state]);
return (
<div className="App">
<h1>State: {state.toString()}</h1>
<button onClick={() => setState(false)}>update</button>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
const { useState, useEffect } = React;
function App() {
const [state, setState] = useState(true);
useEffect(() => {
const timeout = setTimeout(() => {
console.log(state);
}, 5000);
return () => {
// clears timeout before running the new effect
clearTimeout(timeout);
};
}, [state]);
return (
<div className="App">
<h1>State: {state.toString()}</h1>
<button onClick={() => setState(false)}>update</button>
</div>
);
}
ReactDOM.render(<App />, document.querySelector("#root"));
Run Code Online (Sandbox Code Playgroud)
如果您想在不增加延迟的情况下运行超时,则可以使用替代解决方案。如果延迟后状态发生变化,则不会启动新的超时。
您可以使用useRef
钩子随时获取最新状态的引用。
这是一个例子。您可以修改以下内容以使用您的变量和逻辑。
export default function App() {
const [state, setState] = useState(true);
const stateRef = useRef(state);
// this effect doesn't need any dependencies
useEffect(() => {
const timeout = setTimeout(() => {
// use `stateRef.current` to read the latest state instead of `state`
console.log(stateRef.current);
}, 5000);
return () => {
// just to clear the timeout when component unmounts
clearTimeout(timeout);
};
}, []);
// this effect updates the ref when state changes
useEffect(() => {
stateRef.current = state;
}, [state]);
return (
<div className="App">
<h1>State: {state.toString()}</h1>
<button onClick={() => setState(false)}>update</button>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>
Run Code Online (Sandbox Code Playgroud)
export default function App() {
const [state, setState] = useState(true);
const stateRef = useRef(state);
// this effect doesn't need any dependencies
useEffect(() => {
const timeout = setTimeout(() => {
// use `stateRef.current` to read the latest state instead of `state`
console.log(stateRef.current);
}, 5000);
return () => {
// just to clear the timeout when component unmounts
clearTimeout(timeout);
};
}, []);
// this effect updates the ref when state changes
useEffect(() => {
stateRef.current = state;
}, [state]);
return (
<div className="App">
<h1>State: {state.toString()}</h1>
<button onClick={() => setState(false)}>update</button>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
10230 次 |
最近记录: |