简体   繁体   中英

setState update array value using index in react

I want to update array value using index, is below code ok?

handleChange = index => e => {
  const { rocket } = this.state // ['tesla', 'apple', 'google']
  rocket[index] = e.target.value
  this.setState({ rocket })
}

my jsx

<div>{rocket.map((val,i) => <input type="text" onChange={handleChange(i)} value={val} />)}</div>

I know it worked, but just to be sure it's ok to mutate the state like that.

It's not okay to mutate state this way.

The following line mutates the array in the current state in a way that can lead to bugs in your program particularly with components down the Component tree using that state.
This is because the state is still the same array.

rocket[index] = e.target.value
//console.log(this.state.rocket) and you see that state is updated in place

Always treat state as immutable

You can remedy this by writing.

const newRocket = [
  ...rocket.slice(0, index),
  e.target.value, 
  ...rocket.slice(index + 1)
]

This way a new array is created and components in the Component tree can be updated when React does a reconciliation .

Note that
The only way to mutate state should be through calls to Component.setState .

Now that you have a new array, you can update the component state like so:

this.setState({ rocket: newRocket })

Instead of changing existing value, you could use Array.prototype.splice() .

The splice() method changes the contents of an array by removing existing elements and/or adding new elements.

 var arr= ['A','B','E','D']; arr.splice(2,1,'C') console.log(arr)//The result will be ['A','B','C','D']; 
 .as-console-wrapper {max-height: 100% !important;top: 0;} 

Stackblitz demo


CODE SNIPPET

class App extends Component {
  constructor() {
    super();
    this.state = {
      name: 'Demo using Array.prototype.slice()',
      rocket: ['tesla', 'apple', 'google'],
      link: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice'
    };
  }

  handleChange(index, e) {
    const { rocket } = this.state;
    rocket.splice(index, 1, e.target.value)
    this.setState({ rocket: [...rocket] }, () => {
      //call back function of set state you could check here updated state
      console.log(this.state.rocket)
    });
  }

  render() {
    return (
      <div>
        <b><a target="_blank" href={this.state.link}>{this.state.name}</a></b>
        {
          this.state.rocket.map((val, i) =>
            <p key={i}>
              <input type="text" onChange={(e) => { this.handleChange(i, e) }} value={val} />
            </p>)
        }</div>
    );
  }
}

render(<App />, document.getElementById('root'));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM