2

I was reading the react documentation State Updates are Merged and theres a part it says when we set a object like this eg: this.setState({comments}) it completely replaces this.state.comments.

So, I wonder if the approach to change name of user object on event onChangeText is valid, because the whole object it'll be replaced everytime onChangeText is called.

Is that a good practice or have side effects like bad perfomance?

example code:

this.state = {
    user:{
        name: "",
        surname: "",
    },
    isLoading: false
};
/***/
onChangeText={name => this.setState({
  user: {
    ...user,
    name
  }
})}

3 Answers3

1

Inmutability is one point performance is another.

Inmutability meas that you should not use the same reference to update an object but to replace with a new one. In React this is recommended because plenty of updates only happen if the object is new. You could create a problem if you re-use the user in the state, change the name and then update the state with it. And that is why it is a recommendation, in most cases React magic will work on others it can't tell the difference. So you would have to

const copy = Object.assign({}, this.state.user);

You can see this explanation here in the power of not mutating data

Performance in this case is concerning you because is a text listener, nevermind about it, React keeps track of the UI in a virtual DOM so it can update only what is different. This means everything will remain the same except for the new or deleted character.

You can try the clock example in the doc for that.

cutiko
  • 9,887
  • 3
  • 45
  • 59
0

I'd recommend set from lodash/fp: https://gist.github.com/jfmengels/6b973b69c491375117dc#_setpath-value-object

Markus
  • 1,598
  • 2
  • 13
  • 32
0

Your example is perfectly valid, provided the user variable is up-to-date. To ensure that, you might want to use the function arg form of setState. This will call your function with the current value of this.state and set state to the returned value.

onChangeText={
  name => 
    this.setState(
      ({ user }) => ({
        user: { ...user, name }
      })
    )
}
lecstor
  • 5,619
  • 21
  • 27
  • I understand, but i don't think is a good pratice replace whole object every time `onChangeText` is called. – Eduardo Breno Mar 09 '19 at 11:37
  • you need to replace the top level object, or React won't detect the change and re-render. It's the premise of immutibility and change detection. With that code you swap the `user` object for a new object, but keep the same references for it's key values, except for name which you change. – lecstor Mar 09 '19 at 11:41
  • actually, I'm thinking about PureComponent/Memo shallow prop checking. i think `setState` triggers re-render regardless. But if you pass those state values to child components that connect to Redux, or are PureComponents, or Memoed, then depending on where they are in the component props, mutating an object may mean re-renders don't always occur when they should. – lecstor Mar 09 '19 at 11:44