Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

useEffect throw warning for dependecy

I have a dropdown menu which has a controlled state. If the user changed the dropdown value and if the input is not empty, fire a function passed from other component.

export default ({ triggerChange, inputVal }) => {
  const [dropdown, setDropdown] = useState(1);

  useEffect(() => {
    if (inputVal) {
      triggerChange(dropdown);
    }
  }, [dropdown]); // this line throw a warning

  const handleChange = e => {
    setDropdown(e.target.value);
  };

  return (
    <div>
      <select onChange={handleChange}>
        <option value="1">1</option>
        <option value="2">2</option>
      </select>
    </div>
  );
};

codesandbox

Error

React Hook useEffect has missing dependencies: 'inputVal' and 'triggerChange'. Either include them or remove the dependency array. If 'triggerChange' changes too often, find the parent component that defines it and wrap that definition in useCallback. (react-hooks/exhaustive-deps)

like image 272
Hanz Avatar asked Aug 07 '19 03:08

Hanz


2 Answers

Add those to the dependency:

useEffect(() => {
  if (inputVal) {
    triggerChange(dropdown);
  }
}, [dropdown, inputVal]);

This will only re-run the effect if either dropdown or inputVal values change.

For triggerChange:

if dropdown changes frequently, use useCallback hook.

// Parent.js
const memoizedTriggerChange = useCallback(
  () => {
    triggerChange(dropdown);
  },
  [dropdown],
);

useEffect(() => {
  if (inputVal) {
    memoizedTriggerChange();
  }
}, [inputVal]);

EDIT

based on the OPs codesandbox

// index.js
const triggerChange = useCallback(() => {
  console.log("call api");
}, []); // not depending on inputVal to prevent firing if inputVal changes

// AnotherComp.js
useEffect(() => {
  triggerChange(dropdown);
}, [dropdown, triggerChange]);
like image 121
Joseph D. Avatar answered Sep 19 '22 04:09

Joseph D.


useEffect(() => {
    if (inputVal) {
      triggerChange(dropdown);
    }
  }, [dropdown]); // this line throw a warning

In this piece of code, if you notice, inputVal, triggerChange and dropdown are variables and they are dependencies to useEffect hook because useEffect gets triggered whenever any change is made to any of the aforementioned dependencies.

To satisfy the basic working principle of useEffect hook, we should pass those depdencies in useEffect's array parameter.

  useEffect(() => {
    if (inputVal) {
      triggerChange(dropdown);
    }
  }, [dropdown, triggerChange, inputVal]);
like image 35
PrivateOmega Avatar answered Sep 22 '22 04:09

PrivateOmega