Saif Khan
Saif Khan

Reputation: 484

How to setState multiple states?

I have Multiple properties and everyone has it own state. How do I state multiple states at the same time ? There is this one way

ChangeName(event){
        const details = this.state.details;
        details.first_name = event.target.value;
        this.setState({details: details});
    }

and bind it this way

this.ChangeName = this.ChangeName.bind(this);

So I have a form with these different properties

this.state={
        details :{first_name: "",
                last_name:"",
                address:"",
                company:"",
                number:"",
                dob:""
                }

So do I have create function for every property and bind everyone separately the way I mentioned above ? Or is there any other way that I am not aware of as I am new to react.

Thank you !

Upvotes: 14

Views: 55451

Answers (3)

Jonas Wilms
Jonas Wilms

Reputation: 138235

You could use a curried function and use bracket notation to set different props of the details:

changeDetail(name) {
    return event => {
      this.setState(({ details }) => ({
        details: { ...details, [name]: event.target.value }
      }));
    };
  }

Then you can use it like this in the render() ed elements:

  <input
      onChange={this.changeDetail("lastName")}
      value={this.state.details.lastName}
    />

    <input
      onChange={this.changeDetail("address")}
      value={this.state.details.address}
    />

Upvotes: 4

Sven Tschui
Sven Tschui

Reputation: 1425

To answer your question about updating multiple properties of the state: You can absolutely do this. setState accepts an object with updates. Thus setState({ foo: '', bar: '' }) will update the foo and bar properties.


To answer what I think you meant:

When working with input fields the way to go is to create an event handler function for each field.

See the two examples of how to properly handle input fields with nested state or with top level state. I'd recommend to keep the fields top-level in the state as otherwise you'll have to deal with

https://codepen.io/sventschui/pen/yxPrjP

class AppWithDetails extends React.Component {
  constructor(props) {
    super(props)
    this.onFirstNameChange = this.onFirstNameChange.bind(this);
    this.onLastNameChange = this.onLastNameChange.bind(this);
    this.state = {
      details: { first_name: '', last_name: '' }
    }
  }

  onFirstNameChange(event) {
    // store value because of react synthetic events
    const value = event.target.value;

    // use callback function in setState because of asynchronous nature of setState
    this.setState(function(state) {
      return { 
        details: Object.assign({}, 
          state.details, {
          first_name: value 
        })
      }
    })
  }

  onLastNameChange(event) {
    // store value because of react synthetic events
    const value = event.target.value;

    // use callback function in setState because of asynchronous nature of setState
    this.setState(function(state) {
      return { 
        details: Object.assign({}, 
          state.details, {
          last_name: value 
        })
      }
    })
  }

  render() {
    return (
      <div>
        State:
        <pre>{JSON.stringify(this.state)}</pre>
        <input type="text" onChange={this.onFirstNameChange} value={this.state.details.first_name} />
        <input type="text" onChange={this.onLastNameChange} value={this.state.details.last_name} />
      </div>
    )
  }
}

class AppWithoutDetails extends React.Component {
  constructor(props) {
    super(props)
    this.onFirstNameChange = this.onFirstNameChange.bind(this);
    this.onLastNameChange = this.onLastNameChange.bind(this);
    this.state = {
      first_name: '',
      last_name: '',
    }
  }

  onFirstNameChange(event) {
    this.setState({ first_name: event.target.value })
  }

  onLastNameChange(event) {
    this.setState({ last_name: event.target.value })
  }

  render() {
    return (
      <div>
        State:
        <pre>{JSON.stringify(this.state)}</pre>
        <input type="text" onChange={this.onFirstNameChange} value={this.state.first_name} />
        <input type="text" onChange={this.onLastNameChange} value={this.state.last_name} />
      </div>
    )
  }
}

document.addEventListener("DOMContentLoaded", function(event) { 
  ReactDOM.render(<AppWithoutDetails />, document.getElementById('withoutdetails'));
  ReactDOM.render(<AppWithDetails />, document.getElementById('withdetails'));
});

Upvotes: 9

hosein khan beigi
hosein khan beigi

Reputation: 34

ChangeName(event){
        this.setState({
           details:{ first_name: 'jack', last_name:'high'}
      });
}
render(){
  const {details} = this.state
  console.log(details.first_name)
}

Upvotes: -2

Related Questions