I have been using useReducer()
to update a counter for a webapp.
Here’s an example of what my code looked like:
type FruitCollection = {
apples: number;
};
const reducer = (
countState: FruitCollection,
action: FruitCountReducerActions,
) => {
switch (action.type) {
case 'addApple': {
myCounter.apples += 1;
return {
...myCounter,
};
}
}
}
I have a counter component:
const ReviewCounter: React.FC = () => {
const { myCounter } = useCountContext();
return (
<span className="review-counter">
{myCounter.apples}
</span>
);
};
This works as expected.
I then refactored my code to create a class for FruitCollection:
class FruitCollection {
public apples: number;
constructor(apples: number) {
this.apples = apples;
}
}
const reducer = (
countState: FruitCollection,
action: FruitCountReducerActions,
): FruitCollection => {
console.log('dispatch action', action);
switch (action.type) {
case 'addApple': {
myCounter.apples += 1;
return myCounter;
}
}
}
After the above refactor, my ReviewCounter
component is not re-rendered when the addApple
action is called. Debugging shows that the count context provider is re-rendered, and the new value is correct.
I think the problem is that I am returning the object myCounter
directly in the refactor, because when I create a new object based on the previous object’s values and return that instead, then the ReviewCounter
component is updated correctly.
So my question is, when using useReducer()
, do I have to always return a new object to get the context to be updated correctly? (And why?) It seems wasteful to me to create a new object when I already have an object that has the correct values.
Note that I’m using React 18.