简体   繁体   中英

How do you update individual properties of objects in React component states?

I am creating a simple React app that allows the user to add contacts to a master list. My components state looks like this:

state = {
        contact: {
            fname: "",
            lname: "",
            address: "",
            phone: "",
            email: "",
            id: ""
        }
    };

So far, I have been able to effectively add properties such as name, email, etc using values sent from inputs.

this.setState({
    contact: {
        ...this.state.contact,
        [e.target.name]: e.target.value // e is an event sent from an input
    }
});
    };

That's all fine and dandy, but I need each contact to have a unique ID. I have been trying to tack on the ID to the contact object before I send it up the component hierarchy.

const unId = new Date().getTime();
this.setState({
    contact: {
        ...this.state.contact,
        id: unId
    }
});

This code is producing some strange issues and I'm not sure why. When I run it for the first time, the id is generated, but not assigned to the contact. The second time I run it, the id produced the first time is assigned to the second contact. In other words, the id property is updating the state later one cycle behind the time it should.

I'm not very familiar with synchronicity or anything in React, so I would really appreciate any help I could get.

Does this example help you? If not, can you comment what do you exactly want?

https://codesandbox.io/s/priceless-mccarthy-7i69e

import React, { Component } from "react";

class App extends Component {
  state = {
    contact: {
      fname: "",
      lname: "",
      address: "",
      phone: "",
      email: "",
      id: new Date().getTime()
    }
  };

  handleInputChange = e => {
    this.setState({
      contact: {
        ...this.state.contact,
        [e.target.name]: e.target.value
      }
    });
  };

  handleSubmit = e => {
    console.log(this.state);
  };

  render() {
    const { fname, lname, address, phone, email, id } = this.state.contact;

    return (
      <div>
        <label>fname</label>
        <input
          type="text"
          value={fname}
          name="fname"
          onChange={this.handleInputChange}
        />
        <br />
        <label>lname</label>
        <input
          type="text"
          value={lname}
          name="lname"
          onChange={this.handleInputChange}
        />
          <br />
        <label>address</label>
        <input
          type="text"
          value={address}
          name="address"
          onChange={this.handleInputChange}
        />
          <br />
        <label>phone</label>
        <input
          type="text"
          value={phone}
          name="phone"
          onChange={this.handleInputChange}
        />
          <br />
        <label>email</label>
        <input
          type="text"
          value={email}
          name="email"
          onChange={this.handleInputChange}
        />
          <br />
        <label>id</label>
        <input
          type="text"
          value={id}
          name="id"
          onChange={this.handleInputChange}
        />
        <button type="button" onClick={this.handleSubmit}>
          Submit
        </button>
        <hr />
        {
          JSON.stringify(this.state)
        }
      </div>
    );
  }
}

export default App;

The ID isn't created until the next render because the component's state isn't initialized when it gets created. You need to initialize its state.

Either in a class constructor

    constructor() {
      super();
      this.state = {
        id: new Date().getTime()
      }
    }

or a state attribute

    state = {
      id: new Date().getTime()
    }

Here is a working codepen example

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