3

I want to use React.useReducer to update state. My state is an array of objects. When update action is triggered, not only value from desired index is updated but all of them. I want to have updated only the value from indicated array index. How can I do that?

After I click button1, I want to get

[{"amount":null,"kcal":null,"name":null,"isPieceType":false},
{"amount":null,"kcal":null,"name":null,"isPieceType":false},
{"amount":null,"kcal":125,"name":null,"isPieceType":false},
{"amount":null,"kcal":null,"name":null,"isPieceType":false}]

instead of

[{"amount":null,"kcal":125,"name":null,"isPieceType":false},
{"amount":null,"kcal":125,"name":null,"isPieceType":false},
{"amount":null,"kcal":125,"name":null,"isPieceType":false},
{"amount":null,"kcal":125,"name":null,"isPieceType":false}]

I tried to copy state as const newState = [...state] and use lodash's cloneDeep. Below, link to jsfiddle with code to reproduce.

https://jsfiddle.net/wtj5eyfh/

Amila Senadheera
  • 12,229
  • 15
  • 27
  • 43
Zaharskyy
  • 99
  • 3
  • 10

1 Answers1

1

Your initial state of ingredientsState has references to the same object called initialIngredient. That caused everything to update when one entry was updated. Even though const stateToUpdate = [...state]; created a new array again all entries refers to the same object.

Fix

Change the following referenced array entries

const [ingredientsState, ingredientsDispatch] = React.useReducer(mealReducer, [
    initialIngredient,
    initialIngredient,
    initialIngredient,
    initialIngredient
]);

To be an array of copies of initialIngredient object (spread operator simply create clones of the referred object)

const [ingredientsState, ingredientsDispatch] = React.useReducer(mealReducer, [
    { ...initialIngredient },
    { ...initialIngredient },
    { ...initialIngredient },
    { ...initialIngredient }
]);

JS Fiddle

Amila Senadheera
  • 12,229
  • 15
  • 27
  • 43