Home > Blockchain >  eslint wants me to add a dependency to useEffect but doing so causes an infinite loop
eslint wants me to add a dependency to useEffect but doing so causes an infinite loop

Time:09-30

I appreciate this is a common issue on here but I'm struggling to think of a workaround for my particular situation. My code works as intended but I'm getting an eslint warning about the missing dependency in useEffect. The missing dependency is a function which sends the state to the parent, but if I add it as a dependency it causes an infinite loop.

Here's my child component CheckboxGroup.js:

The itemId and checkedState get lifted from its child (CheckboxItem.js) and the selectedItemIds state gets updated. I've then used useEffect because selectedItemIds needs to get lifted to its parent (App.js) immediately. As you can see, it's missing onSelectHandler in its list of dependencies.

const CheckboxGroup = (props) => {
  const categoryName = props.items[0].category;

  const [selectedItemIds, setSelectedItemIds] = useState([
    ...props.defaultCheckboxIds,
  ]);

  const clickHandler = (itemId, checkedState) => {
    checkedState
      ? setSelectedItemIds((prev) => [...prev, itemId])
      : setSelectedItemIds((prev) => prev.filter((c) => c !== itemId));
  };

  //destructure prop
  const onSelectHandler = props.onSelectHandler;

  useEffect(() => {
    onSelectHandler(categoryName, selectedItemIds)
  }, [categoryName, selectedItemIds]);

  return (
    <ul className="card__inner">
      {props.items.map((item) => {
        return (
          <CheckboxItem
            isChecked={selectedItemIds.includes(item.id)}
            id={item.id}
            name={item.name}
            price={item.price}
            category={item.category}
            key={item.id}
            onClick={clickHandler}
          />
        );
      })}
    </ul>
  );
};

Here's the function in App.js which receives the data and then updates the selections state.

  const [selections, setSelections] = useState({
    chairs: 2,
    tables: 8,
    "large tables": [10, 12]
  });

  const selectionHandler = (selectedCategoryName, selectedItemIds) => {
    setSelections((prev) => ({
      ...prev,
      [selectedCategoryName]: selectedItemIds,
    }));
  };

So I'm wondering if there's a way I can either include the dependency in useEffect without it triggering an infinite loop or there's an alternative way of lifting the state, perhaps without useEffect?

Any help appreciated, thanks.

CodePudding user response:

You can use useCallback from React to memoize selectionHandler. This way you can safely add it in the dependency array:

const selectionHandler = useCallback((selectedCategoryName, selectedItemIds) => {
  setSelections((prev) => ({
    ...prev,
    [selectedCategoryName]: selectedItemIds,
  }));
}, []);
  • Related