我们是否在依赖数组中的useEffect中使用了所有变量?

时间:2019-05-20 18:35:19

标签: reactjs react-hooks

我知道useEffect的依赖项如何工作。但是在我的场景中,我不应该看我将prop值的更改用作处理流的条件,但是如果不将其放在依赖关系数组中,则会收到react-hooks / exhaustive-deps警告。

我的情况是,如果foo和fetchValue更改,我想重新运行整个提取。尽管我使用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 />

}

3 个答案:

答案 0 :(得分:1)

ESLint规则可以通过useEffect钩提供安全性。

如果您完全确定该值不是useEffect的依赖项,则可以添加注释以忽略ESLint规则:Disabling Rules with Inline Comments

我建议添加// eslint-disable-next-line而不是文件范围的eslint-disable

这里是more context about this by Dan Abramov

  
    

有什么方法可以专门针对使用传播运算符的地方禁用此规则吗?

  
     

如果您认为自己知道自己在做什么,可以随时// eslint-disable-next-line react-hooks/exhaustive-deps

答案 1 :(得分:1)

本应将所有使用的变量放入useEffects'deps'数组中的原因未这样做,可能会由于数据过时而产生奇怪的问题。


例如,给定您的用例,假设您的组件prop最初是{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不变的情况下不做任何事情?还是foobar可以组合成一个道具,以便它们一起改变?

答案 2 :(得分:-2)

类似的逻辑经常在'useEffect'中的if语句中发生。首先,根本不需要添加依赖项,您可以将其保留为空。

现在您可以做一些事情,要么简单地忽略警告,因为您的代码看起来不错。或在barfetchValue()的参数的地方重构代码。所以你的代码应该是:

const Component = ({ foo, bar, fetchValue }) => {
  useEffect = (
    () => {
      if(foo) {
        fetchValue(bar);        
      }
    },
    [foo, fetchValue] 
  )

  return <div />

}

然后用fetchValue(baz)开始if(baz){ //your code}声明。

虽然有点麻烦。

您需要问自己,为什么foo或bar会发生变化,为什么?在哪里?在组件本身内部?然后不应该将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 />

}