javascriptreactjshtml-inputtargetingstate-management

Updating nested state in objects through an input element in React


I am creating a form that allows orders to be updated. The input fields have to be populated with the current state of each object that I render and I'd like to be able to edit the input field. I have simplified my code to just one input field and believe that I'm able to do the majority of what I'm attempting using the following code --

class EditOrderForm extends React.Component {
  ...

  handleChange(e, key) {
    const order = this.props.orders[key];
    const updatedOrder = {
      ...order,
      [e.target.name]: e.target.value
    }
    this.props.updateOrder(key, updatedOrder);
  }

  renderEditOrderForm(key) {
    const order = this.props.orders[key]
    return (
      <div key={key}>
        <form >
          <input type="text" name="name" value={order.data.name} placeholder="order name" onChange={(e) => this.handleChange(e, key)} />
          ...
        </form>
      </div>
    )
  }

  render() {
    return (
      <div>
        <h2>Edit Orders</h2>
        {
          Object.keys(this.props.orders).map(this.renderEditOrderForm)
        }
      </div>
    )
  }
}

*************Parent Component*************

class AppComponent extends React.Component {
import EditOrderForm from './EditOrderForm';
...

  updateOrder(key, updatedOrder) {
    const orders = [...this.state.orders]
    orders[key] = updatedOrder;
    this.setState({ orders: orders });
  }

...
}

The state that's set at the parent component level is an array of objects and the data structure for the objects that I'm passing to renderEditOrderForm() has the structure --

{ 
  data: Object,
  meta: Object,
  __proto__: Object
}

Where data: Object contains the key-value pairs that I'm trying to change, in this case the key name nested under data: Object (above) and I would like put it back into the array once updated/edited. I am slightly able to update the name of an order however when I try to update it (say, type an 'x') the object now has this structure --

{ 
  data: Object,
  meta: Object,
  name: "John Smithx"
  __proto__: Object
}

I can intuit that [e.target.name]: e.target.value is probably the culprit, however I'm completely at a loss as to how I'm supposed to access the nested key name in data: Object -- I have tried e.target.data.name, however that gives me undefined and have tried a variety of other combinations. Without using Redux (unfortunately don't have time to learn due to time constraints), does anyone know how I can access/target the key name in order to update nested in data: Object?


Solution

  • You need to change the field order.data.name but your code is only adding a new field to the order object. Replace

    handleChange(e, key) {
        const order = this.props.orders[key];
        const updatedOrder = {
          ...order,
          [e.target.name]: e.target.value
        }
        this.props.updateOrder(key, updatedOrder);
    }
    

    with

    handleChange(e, key) {
        const order = this.props.orders[key];
        let updatedOrder = { ...order };
        updatedOrder.data[e.target.name] = e.target.value;
        // or if you have only 1 field called name, you can use updatedOrder.data.name = e.target.value;
        this.props.updateOrder(key, updatedOrder);
    }