Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 我们在依赖项数组中使用的所有变量是否都有效?_Reactjs_React Hooks - Fatal编程技术网

Reactjs 我们在依赖项数组中使用的所有变量是否都有效?

Reactjs 我们在依赖项数组中使用的所有变量是否都有效?,reactjs,react-hooks,Reactjs,React Hooks,我知道useEffect的依赖项是如何工作的。然而,在我的场景中,我不应该观察prop值的变化,我使用它作为处理流的条件,但是如果我不将它放在dependencies数组中,我将得到react hooks/deps警告 我的场景是,如果foo和fetchValue发生变化,我想重新运行整个fetch。虽然我使用bar作为条件来决定是否调用fechValue,但在我的业务逻辑中,bar的更改不应使块重新运行 const Component = ({ foo, bar, fetchValue })

我知道useEffect的依赖项是如何工作的。然而,在我的场景中,我不应该观察prop值的变化,我使用它作为处理流的条件,但是如果我不将它放在dependencies数组中,我将得到react hooks/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,而不是文件范围的eslint disable

这是:

是否有任何方法可以专门针对使用spread运算符的位置禁用此规则

如果您认为自己知道自己在做什么,则可以随时//eslint禁用下一行react hooks/deps


像这样的逻辑在“useffect”中的if语句中经常出现。首先,根本不需要添加依赖项,您可以将其保留为空

现在,您可以做一些事情,或者干脆忽略警告,因为您的代码看起来很好。或者重构代码,其中bar是fetchValue的参数。所以你的代码应该是:

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

  return <div />

}

之所以要将所有使用的变量放入useEffects“deps”数组中,是因为不这样做可能会由于过时的数据而产生奇怪的问题

例如,给定您的用例,假设您的组件道具最初是{foo:false,bar:false}假设fetchValue是某个固定函数,然后它们更改为{foo:true,bar:true}。在这种情况下,组件将按预期调用fetchValue


但作为另一个例子,假设您的道具从{foo:false,bar:false}更改为{foo:true,bar:false},然后更改为{foo:true,bar:true}。在本例中,尽管道具与上一个示例末尾的道具相同,但fetchValue尚未激发

也许这本身并没有错,但它肯定是怪异和不直观的:理想情况下,您的组件应该基于其道具保持一致的行为,而不管道具的更改顺序如何

因此,是的,您可以始终忽略deps数组以使其不完整,但我个人建议寻找另一种解决方案


如果没有关于用例的更多信息,就很难说得具体,但是也许对fetchValue的调用可以被记忆,这样在foo没有改变的情况下它就不会做任何事情了?或者,foo和bar可以组合成一个单独的道具,这样它们就可以一起改变了?

当然可以。我知道如何禁用警告。我只想讨论的是一些避免警告并以正确方式执行的伟大工具。该工具用于捕获常见用例中的bug,例如useEffect中使用的外部变量,它进行了一些优化以防止每次重新渲染时调用。您所描述的是一个边缘情况,该工具不支持它,因此您应该知道您正在做什么并禁用该规则。我提供了Dan Abramov的一条评论,解释了这一点。重构fetchValue并不能解决任何问题,因为代码仍然在useEffect中使用bar值。我支持第二部分,如果值在useEffect中不相关,那么代码可能会被重构以删除它在useEffect中的用法。您的两个示例仍然会提出相同的linter警告,将道具移动到状态通常不是一个好主意。这意味着组件将完全忽略对这些道具的更改,这通常是不需要的。也许我当时做了一些奇怪的事情,因为当我在一个类似的用例中偶然发现这个警告,后来不得不将道具更改为自定义延迟状态时,警告消失了:useEffect=>{if toggleComponents{const getElem=document.getElementByIdinputId;const getValue=getElem.value?getElem.value:getCheckedinputId;setValuegetValue;}setToggleComponentseditMode;}[editMode];这里没有警告。@Retsam你在做一个奇怪的论点。你说道具的改变不会影响useEffect,但不知怎么的,这可能是状态的问题?这是非常假设的,你能提供一个更具体的例子让我们展开吗?@MarkoGrešak第二个代码片段是一个具体的例子。通过复制foo i在初始渲染时,将忽略foo的所有未来值:useState只读取其默认值一次。这与UseEffect完全不同。假设您的道具从{foo:false,bar:false}更改为{foo:true,bar:false}它会在那里开火,据我所知,这就是@WendellLiu想要的。只是因为,然后变成{foo:true,bar:tr
ue}不需要触发。@Robbeoli useEffect将在那里触发,但fetchValue不会被触发,因为它被包装在ifbar中,而bar仍然是假的。哦,是的,这是真的,对我来说,这种使用感觉是直观的。我将bar视为确定获取值是否正确的某种状态,将foo视为需要为真的实际触发器,并检查bar状态是否为真。@Retsam如果bar是此组件中的一种状态,该怎么办?我是否需要将其添加到依赖项数组中以获取useEffect中的最新值?@NiyasNazar是-deps数组中唯一不需要包含的内容是在组件外部定义的内容,例如导入或模块级变量,以及由React状态设置器、分派函数保证为常量的内容,和ref objects。这听起来不像是一个有效的商业案例,更像是要求在将来调试竞争条件时遇到困难-请您详细描述一下为什么需要这样做?
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 />

}