3
votes

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?

2

2 Answers

3
votes

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

0
votes

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