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,
}));
}, []);