【问题标题】:Can we use a function as second arguments in useEffect我们可以在 useEffect 中使用函数作为第二个参数吗
【发布时间】:2019-10-18 21:29:32
【问题描述】:

我有以下功能:

function handleEnterPress(e) {
    if (e.keyCode === 13) {
      if (value !== "") {
        let toAdd = true;
        chips.forEach(chip => {
          if (chip.value === value) {
            toAdd = false;
          }
        });
        if (toAdd) {
          let chipsCopy = [...chips, { value, isDisabled: false }];
          setChips(chipsCopy);
        }
      }
      setValue("");
    }
  }

我在下面useEffect:

useEffect(() => {
    inputRef.current.addEventListener("keyup", handleEnterPress);
    return () =>
      inputRef.current.removeEventListener("keyup", handleEnterPress);
  }, [value]);

现在 react 给我一个警告:

React Hook useEffect 缺少依赖项“handleEnterPress”。

在第二个参数数组中添加handleEnterPress有什么不同?

【问题讨论】:

    标签: reactjs react-hooks use-effect


    【解决方案1】:

    在第二个参数数组中添加handleEnterPress有什么不同。

    为你?没有警告的更简洁的代码。
    对于反应?就是它与useEffect 一起工作的方式。

    要移除此警告,您需要将handleEnterPress 添加到useEEfect 的依赖数组中

    useEffect(() => {
        inputRef.current.addEventListener("keyup", handleEnterPress);
        return () =>
          inputRef.current.removeEventListener("keyup", handleEnterPress);
      }, [value, handleEnterPress]);
    

    之所以需要这个,是因为 react 不知道 handleEnterPress 做什么,或者是什么。如果handleEnterPress 是一个变量并且它的值发生了变化怎么办?如果您更改handleEnterPress,您将需要再次“运行”效果,但如果您只使用[value],当handleEnterPress 更改时它不会“运行”。在你的情况下,也许它永远不会改变,但 react 不知道,所以......它告诉你添加为依赖项。

    例如

    1 .在useEffect 中,添加一个事件监听器。

    inputRef.current.addEventListener("keyup", handleEnterPress);
    
    1. 但是你改变了handleEnterPress的值(很多情况不是你的情况,但这是useEffect所期望的)
      而你在useEffect的依赖中没有handleEnterPress,所以不运行效果。

    2. 然后value发生变化,效果清理发生

      () => inputRef.current.removeEventListener("keyup", handleEnterPress);
      

    在这一部分中,您将尝试使用handleEnterPress 的新值删除handleEnterPress,但不是第一步中的值,因此您将尝试删除不存在的事件侦听器。

    永远不会删除包含旧值的第一个 handleEnterPress。

    这很糟糕,这就是您需要添加 handleEnterPress 作为依赖项的原因

    编辑:

    当chips 发生变化时,handleEnterPress 也会发生变化,并且因为您没有将handleEnterPress 添加到依赖数组中,所以您将始终拥有handleEnterPress 的旧值以及chips 的旧值.

    您的情况在我的回答中进行了解释,是 handleEnterPress 发生变化,但事件侦听器仍然具有 handleEnterPress 的旧值的情况

    【讨论】:

    • 感谢您的回答。但实际上在我的情况下,如果你看到 handleEnterPress 函数,我在那里使用了一个反应状态“芯片”。因此,当我不将此函数添加到 useEffect 的第二个参数数组时,其他副作用中发生的“筹码”的任何变化都不会反映在此函数中。它采用相同的旧筹码价值。你能帮忙吗?
    • @harshit 检查我的编辑。您认为这不是您的情况,但实际上,当chips 更改时,handleEnterPress 也会更改。这就是为什么你需要添加handleEnterPress作为依赖,否则,它将引用chips的旧值
    • 但据我所知,在 Hooks 中,每个渲染 handleEnterPress 都会重新贴花,它会获得芯片的更新值,当“值”发生变化时,我的效果也会运行。所以再次新的侦听器将附加更新的“筹码”值。仅供参考:在我的情况下,状态“值”的值正在改变。
    • 因为您没有将handleEnterPress 添加到依赖项中,所以您永远不会清理您添加的第一个handleEnterPress,因此旧值将始终存在。 handleEnterPress 将在每次渲染时更新。但是第一个inputRef.current.addEventListener("keyup", handleEnterPress); 永远不会被正确清理,因为handleEnterPress 会发生变化。再一次,我在回答中解释了这一点......
    【解决方案2】:

    经过一番谷歌搜索后,我找到了一种更好的方法来做到这一点 我们可以将函数 'handleEnterPress' 函数放入 useEffect 本身:

    useEffect(() => {
        function handleEnterPress(e) {
          if (e.keyCode === 13) {
            if (value !== "") {
              let toAdd = true;
              chips.forEach(chip => {
                if (chip.value.toUpperCase() === value.toUpperCase()) {
                  toAdd = false;
                }
              });
              if (toAdd) {
                let chipsCopy = [...chips, { value, isDisabled: false }];
                setChips(chipsCopy);
              }
            }
            setValue("");
          }
        }
        inputRef.current.addEventListener("keyup", handleEnterPress);
        return () =>
          inputRef.current.removeEventListener("keyup", handleEnterPress);
      }, [value, chips]);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-20
      • 1970-01-01
      • 1970-01-01
      • 2021-04-02
      相关资源
      最近更新 更多