如何将缺少的依赖项添加到仅运行一次的 useEffect 挂钩?
Posted
技术标签:
【中文标题】如何将缺少的依赖项添加到仅运行一次的 useEffect 挂钩?【英文标题】:How to add missing dependencies to a useEffect hook that is run only once? 【发布时间】:2021-03-03 07:40:19 【问题描述】:React Hook useEffect 缺少依赖项:'myDate' 和 'setMyDate'。要么包含它们,要么移除依赖数组。
如何将缺少的依赖项添加到只运行一次的useEffect
?以下示例生成上述警告:
const [ myDate, setMyDate ] = useState(0)
const spinner = useRef(null)
useEffect( () =>
spinner.current = setInterval( () =>
d = Date.now()
if (d < myDate)
setUpdate(d)
, 997 )
, [])
如果我包含它们,我会创建一个无限循环,因为 setTimeout
会更改依赖项的值:
const spinner = useRef(null)
useEffect( () =>
spinner.current = setInterval( () =>
d = Date.now()
if (d < myDate)
setMyDate(d)
, 997 )
, [myDate, setMyDate])
如果我删除依赖数组,useEffect
在每次渲染上运行,并设置无限数量的 setIntervals:
const spinner = useRef(null)
useEffect( () =>
spinner.current = setInterval( () =>
d = Date.now()
if (d < myDate)
setMyDate(d)
, 997 )
)
我还尝试完全删除useEffect
,认为由于spinner
是useRef
,它不会在每个组件渲染上重新分配...但没有:
const spinner = useRef(null)
spinner.current = setInterval( () =>
d = Date.now()
if (d < myDate)
setMyDate(d)
也尝试过使用功能更新方法,就像这样,但是 lint 错误仍然存在并且代码不起作用:
const spinner = useRef(null)
useEffect( () =>
spinner.current = setInterval( () =>
d = Date.now()
setMyDate(d =>
if (d < myDate)
setMyDate(d)
, 997 )
, [setMyDate])
我被卡住了……夹在石头和坚硬的地方之间!如何解决此 lint 警告?
【问题讨论】:
我不知道它是否会起作用,因为有时我有奇怪的无限循环,因为方法没有改变。您可以做的是创建一个设置间隔的方法,并通过将其分配为依赖项来在使用效果中调用此方法。通常它会起作用,因为就像我说的那样,方法不会改变。 你想做什么? @Galupuf 创建一次setInterval
,每n秒调用一次钩子更新。
【参考方案1】:
解决方案是从setMyDate
函数本身获取myDate
(在我的代码中命名为date
),而不是将其作为依赖项传递。
setMyDate
已被记忆,因此不需要作为依赖项传递。
const [myDate, setMyDate] = useState(0);
const spinner = useRef(null);
useEffect(() =>
spinner.current = setInterval(() =>
const d = Date.now();
setMyDate(date =>
if (d < date)
return d;
return date;
);
, 997);
, []);
【讨论】:
不错...功能更新方法。就我而言,myDate
和 setMyDate
是 useContext
钩子,所以 linter 仍在抱怨 setMyDate
@kmiklas 这确实有所作为,您应该在问题中对此进行解释。请编辑您的帖子并添加相关钩子的代码。
瓦伦丁谢谢你。我打算做一个最小的例子。【参考方案2】:
似乎对我有用的是将间隔的逻辑分离到一个没有依赖关系的useCallback()
钩子中。这会记住函数并确保该函数仅在初始组件渲染上构建。
然后,在效果内部调用使用useCallback()
构建的函数,并将其提供给效果依赖项数组。然后,只有在 useCallback()
函数发生变化时才会重建效果——它不会因为它没有依赖关系而重建。
应该从 react-hooks
中删除 linter 警告
import React, useState, useEffect, useRef, useCallback from 'react'
export default function IntervalHook()
const [ myDate, setMyDate ] = useState(0)
const spinner = useRef(0)
const spinnerFn = useCallback(() =>
spinner.current = setInterval(() =>
const d = Date.now()
setMyDate(d)
, 997 )
, [])
useEffect(() =>
spinnerFn()
return () => // this return statement clears the interval when the component unmounts
if (spinner.current)
clearInterval(spinner.current)
spinner.current = 0
, [spinnerFn])
return (
<span>myDate</span>
)
【讨论】:
以上是关于如何将缺少的依赖项添加到仅运行一次的 useEffect 挂钩?的主要内容,如果未能解决你的问题,请参考以下文章
如何绕过 React 的 useEffect() “缺少依赖项”警告?
如何将通过 npm 安装的所有依赖项保存到我的 package.json 文件中?