export const FoodContextProvider = (props) => {
const [selectedFoods, setSelectedFoods] = useState([]);
const [newFood, setNewFood] = useState({});
const [mode, setMode] = useState(null);
const [length, setLength] = useState(selectedFoods.length);
useEffect(() => {
if (mode === "add") {
const duplicate = selectedFoods.some((item) => item.id === newFood.id);
if (duplicate) {
selectedFoods.forEach((item) => {
if (item.id === newFood.id) {
item.amount = newFood.amount;
}
});
} else {
setSelectedFoods((prevFoods) => {
return [...prevFoods, newFood];
});
}
} else {
selectedFoods.forEach((item) => {
if (item.id === newFood.id) {
item.amount = newFood.amount;
}
});
if (newFood.amount < 1) {
setSelectedFoods((prevFoods) => {
return prevFoods.filter((food) => food.id !== newFood.amount.id);
});
}
}
console.log(selectedFoods);
}, [newFood, mode, selectedFoods, setSelectedFoods]);
const selectingFood = (food) => {
setLength((pre) => pre + 1);
setNewFood(food.newFoodItem);
setMode(food.mode);
};
return (
<FoodContext.Provider
value={{
foodItems: foodItem,
selectingFood: selectingFood,
selectedFoods: selectedFoods,
selectedItemLength: length,
}}
>
{props.children} {/* App componnet */}
</FoodContext.Provider>
);
};
hi this is my product count code ,
by calling + button ,it will add product object to the list of selectedFoods state ; and decrease the amount of the products by calling – button
i face infinite loop when i want to remove the product item wich has amount of zero ;
by filtering this object from list of selected products leads to problem
here is what cause problem
if (newFood.amount < 1) {
setSelectedFoods((prevFoods) => {
return prevFoods.filter((food) => food.id !== newFood.amount.id);
});
}
how to prevent this ?
2
Answers
You shouldnt add a lot of dependencies on useEffect, break it to multiple useEffect and verify
There are a couple of issues with that
useEffect
(and some question about whether it should be an effect at all; more on that below):You’re using
selectedFoods
as a dependency, but callingsetSelectedFoods
in the effect. That’s what causes the infinite loop.You’re modifying objects in
selectedFoods
instead of creating a new objects, which breaks the primary rule of state: Don’t directly modify state items. More in the docs.You’re modifying state based on existing state, but the existing state could be stale.
Harmless, but: there’s never any need to list
useState
state setter functions likesetSelectedFoods
in dependency arrays; they’re guaranteed to be stable for the lifetime of the component instance.Instead, pass a callback into
setSelectedFoods
so it calls your code with the up-to-date array. Then you don’t need the array as an effect dependency, and you’re never working with a stale copy. Something like this:Now the effect is only triggered when
newFood
ormode
changes.But stepping back: It seems very odd to have an effect adding and removing items from your
selectedFoods
array. That seems like something that should be happening as a direct action, not as an effect, though of course it’s hard to say without a broader context.