0

I have been trying to wrap my head around the setState. I know the prefered method is to pass setState a function as the method is asynchronous and thus prevent overwritten state changes. So most often this works:

this.setState(() => ({title}))

but what if I have a complex object. My state is like:

{
 movie: { name : 'one', length: 35},
 showLength: false
}

I want to be show the length based on a button click so I want to change the bool to true/false which is easy

this.setState((prevState) => ({showLength : !prevState.showLength}))

but what if I want to edit the name of the movie? Do I have to clone the entire state before I pass it to setState or is there a simpler method. I mean this does not work of cause (but shows my intent):

this.setState((prevState) => ({movie.title:'new title'}))
Todilo
  • 1,256
  • 3
  • 19
  • 38
  • sorry for duplicated. called nested objects. Also had to add "transform-object-rest-spread" to babel to get it working! – Todilo Oct 09 '17 at 20:18

2 Answers2

3

setState can be used multiple ways. You can just pass in an object or you can pass a function inside which gets prevState as a parameter.

So this,

this.setState(() => ({title}))

actually same as doing this,

this.setState((prevState) => {
  return { title: title };
});

So this way you can make complicated changes to your state and return the new value.

Example

this.setState((prevState) => {
  const newState = Object.assign({}, prevState);
  newState.movie.title = 'some new title';
  newState.showLength = !prevState.showLength;
  return newState;
});
bennygenel
  • 23,896
  • 6
  • 65
  • 78
  • hi perfect answer, I am new to react and is it true that conventional setState with object is asynchronous since it has reconciliation but functional setState is synchronous since it doesn't have reconciliation? – Dickens Aug 30 '19 at 11:41
  • The "Example" is the thing I was looking for. Perfect indeed! – jib fashr Dec 11 '20 at 12:18
1

You're correct, you'll have to copy the contents of movie and then update the field you want.

This should work:

this.setState((prevState) => ({...prevState.movie, title:'new title'}))
Chase DeAnda
  • 15,963
  • 3
  • 30
  • 41