2

This works:

  handleOnChange(e) {
    this.setState({[e.target.id]: e.target.value});
  }

e.target.id is wrapped in brackets ([ ]), while e.target.value is not.

I could write e.target.value in brackets too and it would work, but if I remove the brackets from e.target.id my code will not work. Why?

I did some research and believe this is because Computed Property Names (I am not sure though), but then the question arises, why does the property of e.target.id needs to be computed while e.target.value does not? Both of them are simply values I would think.

Dirk J. Faber
  • 3,197
  • 1
  • 11
  • 34
  • `e.target.value` and `[e.target.value]` are not the same. The first will just represent the value while the last will create an array with one entry of the represented value. – Auskennfuchs Jan 08 '20 at 15:29
  • Why the key needs to be computed here is something we can't tell you, because we don't know the context of this code; it depends on how the application that contains this code is constructed, and what the `this.setState()` method expects. – Jesper Jan 08 '20 at 15:30
  • possible duplication https://stackoverflow.com/questions/11508463/javascript-set-object-key-by-variable – netdjw Jan 08 '20 at 15:35

3 Answers3

4

why does the property of e.target.id needs to be computed while e.target.value does not?

The right hand side is always a value (and always has been).

The left hand side is, historically, a string or identifier. The ability to put an expression there (a computed property name) is a new feature.

const foo = "bar";
// Here the property name is foo because it is an identifier
const obj = {
    foo: foo
};
console.log(obj);

// Here the property name is foo because it is a string
const obj2 = {
    "foo": foo
};
console.log(obj2);

// Here the property name is bar because it computed by evauating the constant
const obj3 = {
    [foo]: foo
};
console.log(obj3);


// Here the property name is barbar because it computed by evauating function call that returns a template string that uses the constant twice
function blah() {
    return `${foo}${foo}`;
}
const obj4 = {
    [blah()]: foo
};
console.log(obj4);


//This is the same as the previous example except that because the right hand side is always a value, wrapping the code in square brackets means it is treated as an array literal (as opposed to being a computed property which is what square brackets mean on the left hand side)
function blah() {
    return `${foo}${foo}`;
}
const obj5 = {
    [blah()]: [foo]
};
console.log(obj5);
Quentin
  • 800,325
  • 104
  • 1,079
  • 1,205
2

Because {foo.bar: "fizz"} doesn't mean the same thing as {"foo.bar": "fizz"}, in fact that isn't even syntactically correct.

const a = {b: "c"};
const foo = {a.b: "d"}; // error
console.log(foo);

also consider:

const foo = {
  bar: "other"
};

const b = {
  [foo.bar]: "fizz", // Computed
  "foo.bar": "buzz", // String accessor
  // foo.bar: "err"  // Syntax error
};

console.log(b);

You want the value of foo.bar to be used as the key for the Object. The language mechanism for doing that is to either extract the value and then use brackets to dereference it:

const buzz = {};
buzz[foo.bar] = "fizz";

or you use the new language feature to make it a one-liner:

const buzz = {[foo.bar]: "fizz"};
zero298
  • 20,481
  • 7
  • 52
  • 83
2

I could write e.target.value in brackets too and it would work, but if I remove the brackets from e.target.id my code will not work. Why?

Those two pair of brackets serve very different purpose: in

{ [keyName]: value }

you have indeed a computed property name. In

{ keyName: [value] }

however, the brackets around [value] create an array.

mbojko
  • 9,720
  • 1
  • 10
  • 20