我必须每隔一两秒钟在屏幕上监控一些数据更新信息.我认为使用此实现的方式:
componentDidMount() {
this.timer = setInterval(()=> this.getItems(), 1000);
}
componentWillUnmount() {
this.timer = null;
}
getItems() {
fetch(this.getEndpoint('api url endpoint"))
.then(result => result.json())
.then(result => this.setState({ items: result }));
}
Run Code Online (Sandbox Code Playgroud)
这是正确的方法吗?
Dan*_*uze 37
好吧,既然你只有一个API并且无法控制它以便将其更改为使用套接字,那么你唯一的方法就是轮询.
根据您的民意调查,您正在采取正确的方法.但是上面的代码中有一个问题.
componentDidMount() {
this.timer = setInterval(()=> this.getItems(), 1000);
}
componentWillUnmount() {
this.timer = null; // here...
}
getItems() {
fetch(this.getEndpoint('api url endpoint"))
.then(result => result.json())
.then(result => this.setState({ items: result }));
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是,一旦你的组件卸载了,虽然对你存储的间隔的引用this.timer设置为null,但它还没有停止.即使在卸载了组件之后,该间隔仍将继续调用处理程序,并将尝试setState在不再存在的组件中.
要正确处理它,clearInterval(this.timer)先使用然后再设置this.timer = null.
此外,该fetch调用是异步的,这可能会导致相同的问题.使其可取消,如果有任何fetch不完整则取消.
我希望这有帮助.
Gav*_*ide 26
虽然这是一个老问题,但当我搜索 React Polling 并且没有与 Hooks 一起工作的答案时,它是最高结果。
Run Code Online (Sandbox Code Playgroud)// utils.js import React, { useState, useEffect, useRef } from 'react'; export const useInterval = (callback, delay) => { const savedCallback = useRef(); useEffect(() => { savedCallback.current = callback; }, [callback]); useEffect(() => { function tick() { savedCallback.current(); } if (delay !== null) { const id = setInterval(tick, delay); return () => clearInterval(id); } }, [delay]); }
资料来源:https : //overreacted.io/making-setinterval-declarative-with-react-hooks/
然后您就可以导入和使用了。
// MyPage.js
import useInterval from '../utils';
const MyPage = () => {
useInterval(() => {
// put your interval code here.
}, 1000 * 10);
return <div>my page content</div>;
}
Run Code Online (Sandbox Code Playgroud)
Vas*_*pal 11
setTimeout您可以使用和的组合clearTimeout。
setInterval无论之前的调用是成功还是失败,都会每隔“x”秒触发一次 API 调用。随着时间的推移,这会占用浏览器内存并降低性能。而且,如果服务器宕机了,setInterval会继续轰炸服务器而不知道其宕机状态。
然而,
您可以使用进行递归setTimeout。仅当前一个 API 调用成功时,才会触发后续 API 调用。如果之前的调用失败,请清除超时并且不再触发任何进一步的调用。如果需要,在失败时提醒用户。让用户刷新页面以重新启动此过程。
这是一个示例代码:
let apiTimeout = setTimeout(fetchAPIData, 1000);
function fetchAPIData(){
fetch('API_END_POINT')
.then(res => {
if(res.statusCode == 200){
// Process the response and update the view.
// Recreate a setTimeout API call which will be fired after 1 second.
apiTimeout = setTimeout(fetchAPIData, 1000);
}else{
clearTimeout(apiTimeout);
// Failure case. If required, alert the user.
}
})
.fail(function(){
clearTimeout(apiTimeout);
// Failure case. If required, alert the user.
});
}
Run Code Online (Sandbox Code Playgroud)
小智 5
@AmitJS94,有一个关于如何停止间隔的详细部分,该部分添加到 GavKilbride在本文中提到的方法中。
作者说为延迟变量添加一个状态,并在想要暂停间隔时为该延迟传入“null”:
const [delay, setDelay] = useState(1000);
const [isRunning, setIsRunning] = useState(true);
useInterval(() => {
setCount(count + 1);
}, isRunning ? delay : null);
useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => clearInterval(id);
}
}, [delay]);
Run Code Online (Sandbox Code Playgroud)
一定要阅读这篇文章,以更好地理解细节——它非常彻底,写得很好!
| 归档时间: |
|
| 查看次数: |
15276 次 |
| 最近记录: |