ChatGPT解决这个技术问题 Extra ChatGPT

Reactjs setState() with a dynamic key name?

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?

This is a duplicate of any question concerning dynamic object keys. It's not specific to react
var newstate = {}; newstate[event.target.id] = event.target.id; this.setState(newstate);
Thank you, I didn't have a good handle on using objects in general.
@trad I'm with this problem but, what did you put on your initial State? It doesn't matter, right?

D
Daniel Ruf

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 });
}

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......?
v
vikram jeet singh

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 }); }


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.
s
sintaxi

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)
},

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!!
c
connect2Coder

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 });
},

M
Matthew Holtom

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
  }
});

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

Please mind the quote character.


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

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 :)


C
Catalina

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

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

Hope this helps


J
Jujhar Singh

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


R
Reinaldo EP

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


m
manoj patel

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


H
Hacı Celal Aygar

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});
}

s
sta

Can use a spread syntax, something like this:

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

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/…