简体   繁体   中英

Is there an easier way to setting status in React?

I am just a beginner in React, and I was looking for an easier way to setting status. One important note is that it was inside a functional component.

    const [ personState, setPersonsState ] = useState({
      persons: [
        { name : 'Max', age : 28 },
        { name : 'Manu', age : 29 },
        { name : 'Stephanie', age : 26 }
      ]
    });

I know the way usually is something like this, and this works just fine.

    setPersonsState({
      persons: [
        { name : 'Max', age : 28 },
        { name : 'Ati', age : 29 },
        { name : 'Stephanie', age : 26 }
      ]

But I think it's hard to type it in manually every time, so I tried to make my life easier.

    const newState = personState;
    newState.persons[1].name = 'Ati';
    setPersonsState(newState)

This didn't work, and I don't know why. When I console.log them out it successfully changes, but for some reason the state isn't refreshing, although I use the set command. I also noticed some strange behavior from React, when I used this newState.persons[1].name = 'Ati'; command it also changed the personState variable. So both the personState and the newState variable looked like this in the console.

    {persons: Array(3)}
    persons: Array(3)
    0: {name: "Max", age: 28}
    1: {name: "Ati", age: 29}
    2: {name: "Stephanie", age: 26}
    length: 3
    __proto__: Array(0)
    __proto__: Object

I would appreciate any help or explanation why the this doesn't work.

When you are doing this line const newState = personState; You are not copying the object in personState to newState, but you are taking a referrence of personState and making newState refer to that.

When you make a change to newState, it's like you are changing personState, because referrence for both of these variables is the same. You are directly mutating a state object which is a no-no in React because it doesn't go with the lifecycle, and that is why you are getting this strange behaviour.

If you want to copy the object content to this new variable, you need to do:

const newState = Object.assign({}, personState)

or use Spread syntax

const newState = {...personState }

After that you can go about setting the state with the setPersonState

Note: If you have nested objects, these above given methods will only make a shallow copy meaning only the first level values will be copied.

If you want to make a deep copy of the object, you'll either have to do multiple object spreads (which is a common pattern in redux state management) eg

let state = {a: "val", b: { c: "val" }}

let newState = {
    ...state, 
    b: { 
        ...state.b 
     }
}

or use lodash's deepClone

eg

var objects = [{ 'a': 1 }, { 'b': 2 }];

var deep = _.cloneDeep(objects);

In your code you are trying to directly modify the state. Instead you can copy the array and modify there the value what you need.

I would try to update the state by using .map() as the following in this case:

setPersonsState(prevState => ({
   persons: personState.map(e => {
      if (e.name === 'Manu') e.name = 'Ati';
      return e;
   }));
});

I hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM