Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I setState for nested object?

For a plugin I'm using I have to have a state that looks like this:

getInitialState() {
  return {
    invalid: true,
    access: {
      access_code: '',
      zipcode: '',
      password: '',
      confirm: '',
      hospital_id: '',
    },
  }
},

How would I set the state of hospital_id without setting the rest of access?

This seems to remove everything but hospital_id:

this.setState({access: {hospital_id: 1}})
like image 354
Dan G Nelson Avatar asked Jan 22 '16 21:01

Dan G Nelson


People also ask

How do I change state in nested objects?

To update nested properties in a state object in React: Pass a function to setState to get access to the current state object. Use the spread syntax (...) to create a shallow copy of the object and the nested properties. Override the properties you need to update.

Can we setState in componentDidMount?

You can call setState() immediately in componentDidMount() and triggers an extra rendering, but this happens before the browser updates the screen, calling render() twice.

Can I use setState in another component?

You can't directly call setState on a parent component from a child component because the updating of a component state is restricted to the current component. To handle this, simply pass a function from the parent to the child that contains setState .


4 Answers

You have a few options:

  1. With ECMA6, you can use the Object spread proposal (...) to create copies of objects with updated properties.

    this.setState({
      access: {
        ...this.state.access,
        hospital_id: 1,
      },
    });
    
  2. You can use the native assign function on the Object (Object.assign())

    this.setState({
      access: Object.assign({}, this.state.access, {
        hospital_id: 1,
      }),
    });
    
  3. Or for the shortest version and atomic update:

     this.setState(({access}) => ({access: {
       ...access,
       hospital_id: 1,
     }});
    
  4. And one more option is the updates addon:

    var update = require('react-addons-update');
    // per React docs 
    // https://reactjs.org/docs/update.html 
    // , you may want to change this to 
    // import update from 'immutability-helper';
    this.setState({
      access: update(this.state.access, {
        hospital_id: {$set: 1},
      })
    });
    

I would recommend using the first one.

like image 96
Brigand Avatar answered Oct 17 '22 17:10

Brigand


let newAccess = Object.assign({}, this.state.access);
newAccess.hospital_id = 1;
this.setState({access: newAccess});
like image 39
J. Mark Stevens Avatar answered Oct 17 '22 16:10

J. Mark Stevens


My preferred way of doing this now is as simple as:

let newAccess = this.state.access;
newAccess.hospital_id = 1;
setState({access: newAccess});

Slightly simpler than the current accepted answer.

EDIT (based on the question from @SILENT )

It looks like this is actually a potentially dangerous method. Further reading here React: A (very brief) talk about immutability.

Looks like a better way to do this would be:

let newAccess = Object.assign({}, this.state.access, {hospital_id:1});
this.setState({access: newAccess});
like image 2
Dan G Nelson Avatar answered Oct 17 '22 17:10

Dan G Nelson


Another way to do this would be

const newAccess = {...this.state.access};
newAccess.hospital_id = 1;
setState({access: newAccess});

Use of the spread operator creates a clone of this.state.access.

like image 1
twocents Avatar answered Oct 17 '22 16:10

twocents