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.

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *