如何使用 `onClick` 事件停止调用由 useEffect 挂钩调用的函数?
How to use an `onClick` event to stop calling a function which is called by the useEffect hook?
如何使用 onClick
事件来停止循环函数调用?由于使用 useEffect
、setInterval
和 clearInterval
.
,函数调用重复出现
this article中显示的示例,下面的代码将永远运行。单击 <header></header>
后如何停止调用该函数?
import React, { useState, useEffect } from 'react';
const IntervalExample = () => {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSeconds(seconds => seconds + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
return (
<div className="App">
<header className="App-header">
{seconds} seconds have elapsed since mounting.
</header>
</div>
);
};
export default IntervalExample;
我会像这样从 useEffect 函数中取出区间常量。
import React, { useState, useEffect } from 'react';
const IntervalExample = () => {
const [seconds, setSeconds] = useState(0);
let interval;
useEffect(() => {
interval = setInterval(() => {
setSeconds(seconds => seconds + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
const handleClick = () => {
if (interval) {
clearInterval(interval);
}
}
return (
<div className="App">
<header className="App-header" onClick={() => handleClick()}>
{seconds} seconds have elapsed since mounting.
</header>
</div>
);
};
export default IntervalExample;
添加另一个名为 running
的状态,并使 useEffect
依赖于它。每当 running
切换为 false
时,间隔将被 useEffect
的清理功能清除。由于 running
是 false
,我们跳过设置新间隔。每当切换到 true
时,它将重新启动。
const { useState, useEffect, useCallback } = React;
const IntervalExample = () => {
const [seconds, setSeconds] = useState(0);
const [running, setRunning] = useState(true);
const toggleRunning = useCallback(
() => setRunning(run => !run)
, []);
useEffect(() => {
if(!running) {
// setSeconds(0); // if you want to reset it as well
return;
}
const interval = setInterval(() => {
setSeconds(seconds => seconds + 1);
}, 1000);
return () => clearInterval(interval);
}, [running]);
return (
<div className="App">
<header className="App-header">
{seconds} seconds have elapsed since mounting.
</header>
<button
onClick={toggleRunning}
>
{running ? 'running' : 'stopped'}
</button>
</div>
);
};
ReactDOM.render(
<IntervalExample />,
root
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
我认为停止是指对点击事件说 clearInterval
。所以最好的方法是在一个新的状态变量中保存一个间隔 id。
const IntervalExample = () => {
const [seconds, setSeconds] = useState(0);
const [currentIntervalId, setIntervalId] = useState(null);
useEffect(() => {
const interval = setInterval(() => {
setSeconds(seconds => seconds + 1);
}, 1000);
setIntervalId(interval);
return () => clearInterval(interval);
}, []);
const stopInterval = () => {
clearInterval(currentIntervalId);
};
return (
<div className="App">
<header className="App-header" onClick={stopInterval}>
{seconds} seconds have elapsed since mounting.
</header>
</div>
);
};
- 为什么在状态?
因为这将使您更灵活地重新开始间隔或根据事件随时停止。
注意:你也可以把它放在useEffect
.
范围之外定义的变量中
如何使用 onClick
事件来停止循环函数调用?由于使用 useEffect
、setInterval
和 clearInterval
.
this article中显示的示例,下面的代码将永远运行。单击 <header></header>
后如何停止调用该函数?
import React, { useState, useEffect } from 'react';
const IntervalExample = () => {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSeconds(seconds => seconds + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
return (
<div className="App">
<header className="App-header">
{seconds} seconds have elapsed since mounting.
</header>
</div>
);
};
export default IntervalExample;
我会像这样从 useEffect 函数中取出区间常量。
import React, { useState, useEffect } from 'react';
const IntervalExample = () => {
const [seconds, setSeconds] = useState(0);
let interval;
useEffect(() => {
interval = setInterval(() => {
setSeconds(seconds => seconds + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
const handleClick = () => {
if (interval) {
clearInterval(interval);
}
}
return (
<div className="App">
<header className="App-header" onClick={() => handleClick()}>
{seconds} seconds have elapsed since mounting.
</header>
</div>
);
};
export default IntervalExample;
添加另一个名为 running
的状态,并使 useEffect
依赖于它。每当 running
切换为 false
时,间隔将被 useEffect
的清理功能清除。由于 running
是 false
,我们跳过设置新间隔。每当切换到 true
时,它将重新启动。
const { useState, useEffect, useCallback } = React;
const IntervalExample = () => {
const [seconds, setSeconds] = useState(0);
const [running, setRunning] = useState(true);
const toggleRunning = useCallback(
() => setRunning(run => !run)
, []);
useEffect(() => {
if(!running) {
// setSeconds(0); // if you want to reset it as well
return;
}
const interval = setInterval(() => {
setSeconds(seconds => seconds + 1);
}, 1000);
return () => clearInterval(interval);
}, [running]);
return (
<div className="App">
<header className="App-header">
{seconds} seconds have elapsed since mounting.
</header>
<button
onClick={toggleRunning}
>
{running ? 'running' : 'stopped'}
</button>
</div>
);
};
ReactDOM.render(
<IntervalExample />,
root
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
我认为停止是指对点击事件说 clearInterval
。所以最好的方法是在一个新的状态变量中保存一个间隔 id。
const IntervalExample = () => {
const [seconds, setSeconds] = useState(0);
const [currentIntervalId, setIntervalId] = useState(null);
useEffect(() => {
const interval = setInterval(() => {
setSeconds(seconds => seconds + 1);
}, 1000);
setIntervalId(interval);
return () => clearInterval(interval);
}, []);
const stopInterval = () => {
clearInterval(currentIntervalId);
};
return (
<div className="App">
<header className="App-header" onClick={stopInterval}>
{seconds} seconds have elapsed since mounting.
</header>
</div>
);
};
- 为什么在状态? 因为这将使您更灵活地重新开始间隔或根据事件随时停止。
注意:你也可以把它放在useEffect
.