StrictMode
导致您
useEffect
运行两次,这反过来又导致创建第二个间隔。
问题是在第二个间隔可以被清除之前,ref被重新分配为null。所以你的第二个音程是无限的。
问题演示
function App() {
console.log('rendered')
const deployIntervalRef = React.useRef(null);
React.useEffect(() => {
deployIntervalRef.current = setInterval(() => {
console.log("interval handler");
console.log(deployIntervalRef.current);
clearInterval(deployIntervalRef.current);
deployIntervalRef.current = null;
},2000);
console.log(deployIntervalRef.current);
}, []);
return <div></div>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<React.StrictMode><App/></React.StrictMode>);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js"></script>
<div id="root"/>
不带StrictMode的演示
function App() {
console.log('rendered')
const deployIntervalRef = React.useRef(null);
React.useEffect(() => {
deployIntervalRef.current = setInterval(() => {
console.log("interval handler");
console.log(deployIntervalRef.current);
clearInterval(deployIntervalRef.current);
deployIntervalRef.current = null;
}, 2000);
console.log(deployIntervalRef.current);
}, []);
return <div></div>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<App/>);
<script src=“https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.min.js“></script>
<script src=“https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js“></script>
<div id=“root”/>
重要提示
“为什么”会发生这种行为的答案是
StrictMode
,但这绝不是建议您从应用程序中删除严格模式。
相反,您应该使用另一种方法来清除间隔。这正是事情的类型
使用效果
cleanup函数是为而设计的。
useEffect(() => {
const interval = setInterval(() => {
// your code
},2000);
return () => clearInterval(interval);
}, []);
另一种选择(取决于您的实际用例)是使用超时而不是间隔。您当前的代码只需等待2秒钟即可运行回调,然后再也不会运行。如果您只需要运行一次,请使用
setTimeout
.
useEffect(() => {
setTimeout(() => {
// your code
}, 2000);
}, []);