321

EDIT: this is a duplicate, see here

I can't find any examples of using a dynamic key name when setting the state. This is what I want to do:

inputChangeHandler : function (event) {
    this.setState( { event.target.id  : event.target.value } );
},

where event.target.id is used as the state key to be updated. Is this not possible in React?

5
  • 4
    This is a duplicate of any question concerning dynamic object keys. It's not specific to react Commented Mar 26, 2015 at 14:06
  • 11
    var newstate = {}; newstate[event.target.id] = event.target.id; this.setState(newstate); Commented Mar 26, 2015 at 14:08
  • Thank you, I didn't have a good handle on using objects in general. Commented Mar 26, 2015 at 14:45
  • 1
    Possible duplicate of How do I create a dynamic key to be added to a JavaScript object variable Commented Apr 22, 2016 at 11:04
  • @trad I'm with this problem but, what did you put on your initial State? It doesn't matter, right? Commented Sep 29, 2016 at 18:55

14 Answers 14

325

Thanks to @Cory's hint, i used this:

inputChangeHandler : function (event) {
    var stateObject = function() {
      returnObj = {};
      returnObj[this.target.id] = this.target.value;
         return returnObj;
    }.bind(event)();

    this.setState( stateObject );    
},

If using ES6 or the Babel transpiler to transform your JSX code, you can accomplish this with computed property names, too:

inputChangeHandler : function (event) {
    this.setState({ [event.target.id]: event.target.value });
    // alternatively using template strings for strings
    // this.setState({ [`key${event.target.id}`]: event.target.value });
}
Sign up to request clarification or add additional context in comments.

8 Comments

There's also a new syntax for this, if you're using bablejs to build your code. You can use computed property names
The second approach causes syntax error in browsers on WIndows (IE, Chrome). Did anyone notice?
how to get stated?
Thanks trad, this is what i was looking for to avoid code duplication for <Radio /> implementation.
If you set a state using the computed property name like this: this.setState({ [event.target.id]: event.target.value }); then how would you access that state using this.state......?
|
184

When you need to handle multiple controlled input elements, you can add a name attribute to each element and let the handler function choose what to do based on the value of event.target.name.

For example:

inputChangeHandler(event) {
  this.setState({ [event.target.name]: event.target.value });
}

4 Comments

what do the brackets around [event.target.name] indicate? Why are they required?
As compared to usual approach to named each element separately like this.setState({ userName: e.target.value }); This will handle multiple elements of form as an array and no need to set each individual element
but still how do I access that state in same way ? like this.state([event.target.name]) ?
I think MDN web docs and this post explains why we need the brackets.
50

How I accomplished this...

inputChangeHandler: function(event) {
  var key = event.target.id
  var val = event.target.value
  var obj  = {}
  obj[key] = val
  this.setState(obj)
},

1 Comment

I did similar way but the problem was it still did not render the component, and I ran pillar to post (including this :D), and somewhere found this: this.forceUpdate();which should not have been the case with latest React. Let's see whats the issue later!!
32

I just wanted to add, that you can also use de-structuring to refactor the code and make it look neater.

inputChangeHandler: function ({ target: { id, value }) {
    this.setState({ [id]: value });
},

Comments

15
this.setState({ [`${event.target.id}`]: event.target.value}, () => {
      console.log("State updated: ", JSON.stringify(this.state[event.target.id]));
    });

Please mind the quote character.

2 Comments

exactly what i needed.
Thank you for this, it worked. However could you explain what the [ ] do? Why does react require that?
13

I had a similar problem.

I wanted to set the state of where the 2nd level key was stored in a variable.

e.g. this.setState({permissions[perm.code]: e.target.checked})

However this isn't valid syntax.

I used the following code to achieve this:

this.setState({
  permissions: {
    ...this.state.permissions,
    [perm.code]: e.target.checked
  }
});

Comments

11

In loop with .map work like this:

{
    dataForm.map(({ id, placeholder, type }) => {
        return <Input
            value={this.state.type}
            onChangeText={(text) => this.setState({ [type]: text })}
            placeholder={placeholder}
            key={id} />
    })
}

Note the [] in type parameter. Hope this helps :)

Comments

8

I was looking for a pretty and simple solution and I found this:

this.setState({ [`image${i}`]: image })

Hope this helps

Comments

4

With ES6+ you can just do [${variable}]

Comments

2

when the given element is a object:

handleNewObj = e => {
        const data = e[Object.keys(e)[0]];
        this.setState({
            anykeyofyourstate: {
                ...this.state.anykeyofyourstate,
                [Object.keys(e)[0]]: data
            }
        });
    };

hope it helps someone

Comments

1

Your state with dictionary update some key without losing other value

state = 
{   
    name:"mjpatel"  
    parsedFilter:
    {
      page:2,
      perPage:4,
      totalPages: 50,
    }
}

Solution is below

 let { parsedFilter } = this.state
 this.setState({
      parsedFilter: {
        ...this.state.parsedFilter,
        page: 5
      }
  });

here update value for key "page" with value 5

1 Comment

setState should return a new object.
1

If you are using JS ES6+, it is [${variable}], to set the key:

// In React
onChange={e => setData({ [variable] : e.target.value })}

As well, if you want to access the dynamic key, you just use data[${variable}]:

// In React
value={data[variable]}

Comments

0

try this one please.

State is here as example

 this.state = {
            name: '',
            surname: '',
            username: '',
            email: '',
  }

Onchange function is here.

onChangeData = (type, event) => {
    const stateData = this.state;
    if (event === "" || event === "Seçiniz")
        stateData[type] = undefined
    else
        stateData[type] = event

    this.setState({ stateData});
}

Comments

-3

Can use a spread syntax, something like this:

inputChangeHandler : function (event) {
    this.setState( { 
        ...this.state,
        [event.target.id]: event.target.value
    } );
},

4 Comments

React will do the object merging for you, this is bad practice.
basically if you have some inner object and you want to change one propery on that inner object you do it like this: this.setState({selectedItems:{...selectedItems,[item.id]:true}})
@Rohmer : Why is this considered a bad practice ? If an object has multiple keys, using the spread operator seems to work to preserve all other keys except the one being modified. Or should we use prevState ? Please explain.
If you have nested state like @EranOr mentioned, then doing spread makes sense, but you must use prevState or you won’t be able to guarantee that you’re using the most up-to-date state. However, if you’re just setting a single, top-level state value like in @sta’s answer, then you don’t need to spread on state since React will merge it in for you. reactjs.org/docs/…

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.