0

I want to update value of one object only but updating value of one Object, Updates the value for all objects.

let default = {
    name: '',
    age: ''
}
this.state = {
    values: Array(2).fill(default)
}

updateName (event) {
    let index = event.target.id,
    values = this.state.values;

    values[index].name = event.target.value;

    this.setState ({
        values: values
    });
}
2
  • Welcome to Stack Overflow! Please take the tour, have a look around, and read through the help center, in particular How do I ask a good question? Please be as clear as possible about what you want to do, what you see happening instead, and why that's surprising. Right now, it's not clear. Where possible, include a minimal reproducible example demonstrating the problem, ideally a runnable one using Stack Snippets (the [<>] toolbar button). Stack Snippets support React, including JSX; here's how to do one. Commented Feb 9, 2018 at 6:43
  • 1
    Objects are copied using reference. So both the values in array will point to same object. Instead use inline object or use Object.assign({}, defaultState). default is not a good variable name. Try being a bit specific Commented Feb 9, 2018 at 6:43

3 Answers 3

1

There are four significant problems in that code.

  1. You're using the same object for all entries in your array. If you want to have different objects, you have to create multiple copies of the default.

  2. You're calling setState incorrectly. Any time you're setting state based on existing state (and you're setting values based, indirectly, on this.state.values), you must use the function callback version of setState. More: State Updates May Be Asynchronous

  3. You can't directly modify the object held in this.state.values; instead, you must make a copy of the object and modify that. More: Do Not Modify State Directly

  4. default is a keyword, you can't use it as an identifier. Let's use defaultValue instead.

Here's one way you can address all four (see comments):

// #4 - `default` is a keyword
let defaultValue = {
    name: '',
    age: ''
};
this.state = {
    // #1 - copy default, don't use it directly
    values: [
        Object.assign({}, defaultValue),
        Object.assign({}, defaultValue),
    ] // <=== Side note - no ; here!
};

// ....

updateName(event) {
    // Grab the name for later use
    const name = event.target.value;
    // Grab the index -- I __don't__ recommend using indexed updates like this;
    // instead, use an object property you can search for in the array in case
    // the order changes (but I haven't done that in this code).
    const index = event.target.id;
    // #2 - state updates working from current state MUST use
    // the function callback version of setState
    this.setState(prevState => {
        // #3 - don't modify state directly - copy the array...
        const values = prevState.values.slice();

        // ...and the object, doing the update; again, I wouldn't use an index from
        // the `id` property here, I'd find it in the `values` array wherever it
        // is _now_ instead (it may have moved).
        values[index] = {...values[index], name};

        return {values};
    });
}

Note that this line in the above:

values[index] = {...values[index], name};

...uses property spread syntax added in ES2018 (and shorthand property syntax, just name instead of name: name).

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

1 Comment

@Rajesh: slice just copies the array, the objects in the array are still shared with the state. We have to copy the object, too, prior to modifying it.
0

I would use the Array.prototype.map function with combination of the object spread syntax (stage 4):

Note that i changed the name of the default object to obj.
default is a reserved key word in javascript

let obj = {
    name: '',
    age: ''
}
this.state = {
    values: Array(2).fill(obj)
}

updateName(event){
    const {id, value} = event.target;  
    this.setState(prev => {
    const {values} = prev;

    const nextState = values.map((o,idx) => {
        if(idx !== id)
        return o; // not our object, return as is

      return{
          ...o,
          name: value;
        }
    });

      return{
        values: nextState
      }
    });
}

1 Comment

Good catch on default. It's not just reserved, it's a keyword.
0

There is an easy and safe way to achieve that through the following:

this.setState({
  values: [ newObject, ...this.state.values],
});

this will create an instance of the state and change the value of an existing object with new object.

Comments

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.