1

I have an array of objects

const array = [
  { itemId: "optionOne", name: "Option One", quantity: 10 },
  { itemId: "optionTwo", name: "Option Two", quantity: 20 },
  { itemId: "optionThree", name: "Option Three", quantity: 30 }
];

I need to update just the quantities using input box and then update state. end with something like this enter image description here

whats the best way to do this.

PLEASE find attached code example ready to modify handleChange() function CodeSandbox

4
  • For starters, your array needs to not be defined in your render() function, otherwise it's going to overwrite back to the default values every time it renders Commented Nov 7, 2019 at 21:35
  • @mhodges ah in CodeSandbox, its just an example. array is actually coming from an api. which I use to map over to create input options Commented Nov 7, 2019 at 21:38
  • Are you storing that in the component state? You say you want to "update state", but nothing in the sandbox is using state. Can you update the sandbox to recreate your use-case a little more accurately? Otherwise its hard to tell exactly what you're wanting to accomplish Commented Nov 7, 2019 at 21:40
  • @mhodges Please check now. result comes back from api, and is set to state an passed down to chld component as prop. Commented Nov 7, 2019 at 21:45

2 Answers 2

2

If you want to store and update state, you need to add your data to the component state. This can be done in the constructor, and then modified using setState() in any of your component methods (i.e. if you are getting the data from an API, or modifying with your change handler). The component would look something like this:

constructor(props) {
  super(props);
  // set initial state, set to { array: [] } if getting data from API
  this.state = {
    array: [
      { itemId: "optionOne", name: "Option One", quantity: 10 },
      { itemId: "optionTwo", name: "Option Two", quantity: 20 },
      { itemId: "optionThree", name: "Option Three", quantity: 30 }
    ]
  };
}
handleChange = (itemIndex, itemValue) => {
  console.log(itemIndex, itemValue);
  // set state to changed values
  this.setState({
    array: this.state.array.map((item, index) => {
      // update item quantity (or clone & mutate if you need to maintain immutability)
      if (index === itemIndex) { item.quantity = +itemValue };
      return item;
    })
  });
};
render() {
  return (
    <div>
      {this.state.array.map((item, key) => {
        return (
          <FormGroup controlId="siteVisit">
            <Row>
              <Col xs={12} md={4}>
                <h3>{item.name}</h3>
              </Col>
              <Col xs={12} md={8}>
                <FormControl
                  type="text"
                  key={item.itemId}
                  onChange={item => {
                    this.handleChange(key, item.target.value);
                  }}
                />
                <span>{item.quantity}</span>
              </Col>
            </Row>
          </FormGroup>
        );
      })}
    </div>
  );
}

Edit

While the above solution is relatively simple, depending on your app structure, it might make more sense to use an "event emitter"-like function that you pass through that gets called instead. That way, there is no need to store or update state inside your child component - it becomes stateless and purely presentational. All of the data mutations/updates will happen on the parent and simply be passed down to the child for display. The main reason for wanting to do this is if the data changes and new data gets sent down from the parent. If you're not listening/reacting to changes in the child props, those changes will never trigger updates to your child component unless you explicitly listen for the changes, in which case, you're duplicating code. Anyway, might be overkill for this simple example, but it's something worth thinking about.

Sign up to request clarification or add additional context in comments.

6 Comments

Mate, this work perfectly. thanks. just wanted to ask how can I only return or filter down to itemId and quantity. once I have quantity I then make post request with these two.
@Hman Hmm, I'm not sure what you're asking. What exactly do you want to filter? this.state.array? Or do you want to filter another list based on the values of a given item in this.state.array? Or do you want to strip off all properties of the items in this.state.array except itemId and quantity for sending with post request? Can you please clarify?
strip off all properties of the items in this.state.array except itemId and quantity and their values, spot on mate
@Hman Ah, that should be pretty easy with Array.map(). let strippedItems = this.state.array.map(({itemId, quantity}) => ({itemId, quantity})); would be the shorthand way to do it. If you wanted to be more explicit, you could say let strippedItems = this.state.array.map(item => { return {itemId: item.itemId, quantity: item.quantity}; }); They do the same thing
perfect, Thanks Mate
|
2

As mentioned in the comments, you should be storing your data in the state if you want to edit it. You have a decent start feeding in the index and value to the change function. Then you need to duplicate the array to prevent direct state mutation, alter the value accordingly and use setState to register the changes with React.

Fork here.

4 Comments

Since you mentioned immutability, it might be worth noting that Array.from() is not a deep copy of the array and therefore the objects themselves (on which you are mutating the quantity) are the original objects.
Thanks Mate, you solution works but return string "1" instead of just number 1
Text inputs always stringify everything. @mhodges this is true, I was simply pointing out the steps I took and why you wouldn't edit state directly.
@ChrisB. Yeah, understandable. I just wanted to clarify that without cloning each object, you are editing state directly. Those objects are the same ones that live in the array in state. Again, it's probably not a huge deal for the OP, but something worth mentioning for future readers so they don't get confused about mutability of objects that are nested within state

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.