我想添加setInterval,以便能够在不需要刷新页面的情况下从数据库中获取新数据,所以我使用useEffect、setInterval、useState来解决它,并将初始状态设置为{refresh:false、refreshSells:null}当它打开refresh=true和refreshSells=setinterval((时有开关,但我收到了令人讨厌的警告React Hook useEffect缺少依赖项:"refreshSells"。要么包括它,要么删除依赖数组,如果我添加refreshSells,它将是不可阻挡的循环
const Sells = () => {
const [allSells,setAllSells] = useState([])
const [refresh,setRefresh] = useState(false)
const [refreshSells , setRefreshSells] = useState(null)
const [hidden,setHidden] = useState(true)
useEffect(() => {
Axios.get('/sells')
.then(({data}) => {
setAllSells(data.sells)
})
.catch(() => {
alert('something went wrong,ask omar')
})
},[])
useEffect(() => {
if(refresh){
setRefreshSells(setInterval(() => {
Axios.get('/sells')
.then(({data}) => {
setAllSells(data.sells)
})
}, 60000));
}
else{
clearInterval(refreshSells)
}
return () => clearInterval(refreshSells)
},[refresh])
setRefreshSells
在当前渲染期间更新内部状态并且不更改refreshSells
。因此return () => clearInterval(refreshSells)
将尝试清除错误的间隔。
你应该使用useRef挂钩为你的间隔:
const refreshSellsRef = useRef(null);
...
useEffect(() => {
if(refresh){
refreshSellsRef.current = setInterval(() => {
Axios.get('/sells')
.then(({data}) => {
setAllSells(data.sells)
})
}, 60000);
return () => clearInterval(refreshSellsRef.current);
}
},[refresh])
还要注意,return () => clearInterval(refreshSellsRef.current)
将在卸载和refresh
更改时调用。所以你不需要else {clearInterval(...)}
如果您的业务逻辑允许分离这两种效果(每60秒自动刷新一次+点击某个按钮后手动刷新(,这将简化每个独立效果的代码:
useEffect(() => {
const interval = setInterval(() => {
Axios.get('/sells')
.then(({data}) => {
setAllSells(data.sells)
})
}, 60000)
return () => clearInterval(interval)
}, [])
useEffect(() => {
if (refresh) {
setRefresh(false)
Axios.get('/sells')
.then(({data}) => {
setAllSells(data.sells)
})
};
}, [refresh])
看起来你在触发刷新后忘记了setRefresh(false)
,但我不确定你为什么首先需要refreshSells
。。。
在第二个useEffect
中,您正在更新状态refreshSells
,其中useEffect
期望useCallback
ref作为依赖项。如果将refreshSells
添加为useEffect
的依赖项,则可能会引发内存泄漏问题。
所以我建议你尝试下面的代码,这将解决你的问题。这样你也可以消除refreshSells
useEffect(() => {
let interval;
if (refresh) {
interval = setInterval(() => {
Axios.get('/sells')
.then(({ data }) => {
setAllSells(data.sells)
});
}, 4000);
}
return () => clearInterval(interval);
}, [refresh]);