0

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.

Patrick Kenny
  • 4,515
  • 7
  • 47
  • 76

0 Answers0