Can we use a function as second arguments in useEffect

会有一股神秘感。 提交于 2019-12-12 18:32:16

问题


I have below function:

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("");
    }
  }

and I have below useEffect:

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

Now react gives me a warning:

React Hook useEffect has a missing dependency 'handleEnterPress'.

What difference does it make when we add handleEnterPress in second argument array?


回答1:


What difference does it make when we add handleEnterPress in second argument array.

For you? Cleaner code without warnings.
For React? Is just the way it works with useEffect.

To remove this warning, you need to add handleEnterPress to the dependency array of the useEEfect

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

The reason why you need this, is because react can't know what handleEnterPress do, or what is. What if handleEnterPress is a variable and it's value have changed? If you change handleEnterPress you will need to 'run' the effect again, but if you only use [value], it won't 'run' when handleEnterPress changes. In your case, maybe it will never change, but react can't know that, so... it tells you to add as a dependency.

e.g.

1 . In useEffect, you add an event listener.

inputRef.current.addEventListener("keyup", handleEnterPress);
  1. But then you change the value of handleEnterPress some how (many this is not your case but it's something expected from useEffect)
    And you don't have handleEnterPress in the dependency of useEffect, so it don't run the effect.

  2. Then value changes and the cleanup of the effect happens

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

In this part you will try to remove handleEnterPress with the new value of the handleEnterPress, but not the one in the first step, so you are trying to remove an event listener that don't exists.

The first handleEnterPress containing the old values will never be removed.

This is bad and it's the reason why you need to add handleEnterPress as a dependency

Edit:

When chips change, handleEnterPress changes too, and because you don't add handleEnterPress to the depéndency array, you will always have the old value of handleEnterPress and also the old value of chips.

Your case is explained in my answer, is the case where handleEnterPress changes, but the event listener still have the old value of handleEnterPress




回答2:


After some googling I found a better approach to do this We can put the function 'handleEnterPress' function inside useEffect itself:

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]);


来源:https://stackoverflow.com/questions/56425444/can-we-use-a-function-as-second-arguments-in-useeffect

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!