1

How can I access and set a dynamic e.target.value of a class with setState?

I've tried this.setState({fields[e.target.name]: e.target.value});

class App extends Component  {
  constructor() {
    super();
    this.state = {
      data: [],
      fields: {
        name: ''
      }
    }
  }

  handleChange = e => this.setState({fields[e.target.name]: e.target.value});

  render() {
    const { fields } = this.state;
   
    return (
      <>
        <input type="text" name="name" placeholder="name" onChange={this.handleChange} value={fields.name} />
      </>
    )
  }
}

export default App;

  

1
  • 2
    Nested state is anti-pattern in React: components' state should be kept flat, precisely to face the issue you're facing. Commented Mar 26, 2019 at 22:35

2 Answers 2

5

This is a slightly similar to this question. There are two ways to update the object. And as others have said, nesting state like this is an antipattern. This is a good read-up on why.

1- Simplest one:

First create a copy of fields then do the changes in that:

let fields = Object.assign({}, this.state.fields);    //creating copy of object
fields[e.target.name] =  e.target.value               //updating value
this.setState({fields});

Instead of using Object.assign we can also write it like this:

let fields = {...this.state.fields};

2- Using spread operator:

  handleChange = e => {
    e.persist(); //need to make the values persist because of event pooling
    this.setState(prevState => ({
      ...prevState,
      fields: {
        [e.target.name]: e.target.value
      }
    }))
  }
Sign up to request clarification or add additional context in comments.

2 Comments

The OP wants to update the fields value using e.target.value, not just the name property of the fields
Thanks for pointing that out. Changed the code to reflect that.
4

You can't access a state property like this. A possible solution is to create a copy from the fields, modify the value and then set the new state, like below:

handleChange = e => {  
    // The line below creates a copy of the state, using the spread operator
    let fields = { ...this.state.fields };
    fields[e.target.name] =  e.target.value
    this.setState({fields});
}

4 Comments

I'd use let fields = {...this.state.fields}; instead for simplicity
Or even let fields = [ ... this.state.fields]. Will add it to the answer. Thank you!
Beware, fields is an object, not an array!
@NinoFiliu I haven't noticed that, sorry

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.