Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update an object in 'state' with react redux?

In my reducer, suppose originally I have this state:

{
    "loading": false,
    "data": {
        "-L1LwSwW97KkwdSnYvsc": {
            "likeCount": 10,
            "liked": false,    // I want to update this property
            "commentCount": 5
        },
        "-L1EY2_fqzn7sM1Mbf_F": {
            "likeCount": 8,
            "liked": true,
            "commentCount": 22
        }
    }
}

Now, I want to update liked property inside -L1LwSwW97KkwdSnYvsc object, which is inside data object and make it true. This is what I've been trying, but apparently, it's wrong, because after I've updated the state, the componentWillReceiveProps function inside a component that listens to the state change does not get triggered:

var { data } = state;
data['-L1LwSwW97KkwdSnYvsc'].liked = !data['-L1LwSwW97KkwdSnYvsc'].liked;

return { ...state, data };

Could you please specify why it's wrong and how I should change it to make it work?

like image 475
K.Wu Avatar asked Nov 26 '25 05:11

K.Wu


2 Answers

You're mutating state! When you destructure:

var { data } = state;

It's the same as:

var data = state.data;

So when you do:

data[…].liked = !data[…].liked

You're still modifying state.data which is in turn mutating state. That's never good - use some nested spread syntax:

return { 
  ...state, 
  data: {
    ...state.data,
    '-L1LwSwW97KkwdSnYvsc': {
      ...state.data['-L1LwSwW97KkwdSnYvsc'],
      liked: !state.data['-L1LwSwW97KkwdSnYvsc'].liked
    }
  }
};
like image 86
Andrew Li Avatar answered Nov 29 '25 00:11

Andrew Li


Using spread operator is good until you start working with deeply nested state and/or arrays(remember spread operator does a shallow copy only).

I would rather recommend you starting working with immutability-helper instead. It is a React recommendation and it will let your code more readable and bug free.

Example:

  import update from "immutability-helper";

  (...)

  const toggleLike = !state.data["-L1LwSwW97KkwdSnYvsc"].liked
  return update(state, {
    data: {
      "-L1LwSwW97KkwdSnYvsc": {
        like: {
          $set: toggleLike
        }
      }
    }
  })
like image 31
Cleiton Avatar answered Nov 28 '25 23:11

Cleiton



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!