我知道useEffect的依赖关系是如何工作的。但是在我的场景中,我不应该观察 prop 值的变化,我将其用作处理流的条件,但是如果我不将其放入依赖项数组中,我将收到 react-hooks/exhaustive-deps 警告。
我的情况是,如果foo和fetchValue发生变化,我想重新运行整个fetch。虽然我用 bar 作为条件来决定是调用 fechValue,但在我的业务逻辑中,bar 的更改不应该使重新运行块。
const Component = ({ foo, bar, fetchValue }) => {
useEffect = (
() => {
if(foo) {
if (bar) {
fetchValue();
}
}
},
[foo, fetchValue] // will get a warning `react-hooks/exhaustive-deps`
)
return <div />
}
ESLint 规则是为了提供useEffect
钩的安全性。
如果您绝对确定该值不是useEffect
的依赖项,则可以添加注释以忽略 ESLint 规则:禁用带有内联注释的规则。
我建议添加// eslint-disable-next-line
而不是文件范围的eslint-disable
.
以下是丹·阿布拉莫夫(Dan Abramov)对此的更多背景:
有什么方法可以专门针对使用点差运算符的地方禁用此规则?
如果你认为自己知道自己在做什么,你总是可以
// eslint-disable-next-line react-hooks/exhaustive-deps
。
您应该将所有变量放在useEffects
"deps"数组中的原因不是这样做,可能会由于数据陈旧而产生奇怪的问题。
例如,给定您的用例,假设您的组件 props 最初是{foo: false, bar: false }
的(假设fetchValue
是某个固定函数),然后它们更改为{foo: true, bar: true}
。 在这种情况下,组件将按预期调用fetchValue
。
但作为另一个示例,假设您的道具从{foo: false, bar: false}
更改为{foo: true, bar: false}
,然后更改为{foo: true, bar: true}
。 在这种情况下,fetchValue
没有触发,尽管道具与上一个示例末尾的道具相同。
也许这本身并不"错误",但它肯定是奇怪和不直观的:理想情况下,你的组件应该根据其道具保持一致的行为,并且道具更改的顺序无关紧要。
所以,是的,你总是可以eslint-ignore
deps数组来允许它不完整,但我建议个人寻找另一种解决方案。
如果没有有关用例的更多信息,很难具体说明,但也许可以记住对fetchValue
的调用,以便在foo
没有更改时它不会做任何事情?或者也许foo
和bar
可以组合成一个道具,以便它们一起变化?
像这样的逻辑经常发生在 'useEffect' 中的 if 语句中。首先,根本不需要添加依赖项,您可以将其留空。
现在你可以做一些事情,或者简单地忽略警告,因为你的代码看起来很好。或者重建您的代码,其中bar
是fetchValue()
的参数。所以你的代码将是:
const Component = ({ foo, bar, fetchValue }) => {
useEffect = (
() => {
if(foo) {
fetchValue(bar);
}
},
[foo, fetchValue]
)
return <div />
}
并以if(baz){ //your code}
开始您的fetchValue(baz)
声明。
虽然有点麻烦。
你需要问问自己,你期望foo或酒吧为什么以及在哪里改变?在组件本身内部?foo
和/或bar
不应该是状态,然后foo
和/或bar
作为默认值吗?
const Component = ({ foo, bar, fetchValue }) => {
const [fooState, setFooState] = useState(foo);
const [barState, setBarState] = useState(bar);
useEffect = (
() => {
fooState && barState && fetchValue();
//does the same as your code, I just prefer short circuits for these kind of things.
},
[fooState, fetchValue()]
)
return <div />
}