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.
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.
Share Improve this question asked Oct 19, 2018 at 5:09 Melissa94Melissa94 4231 gold badge5 silver badges12 bronze badges3 Answers
Reset to default 5It'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 ponents 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 ponents 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 ponent 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/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'));
you can try on this
const onChangeProduct = (e, index) => {
console.log("Value price " + e);
const updateItem = [...imports];
updateItem[index]["product"] = e;
setImports(updateItem);
}
<Select
className="w-40"
showSearch
placeholder="Select product"
optionFilterProp="children"
value={element.product}
onChange= {(e) => onChangeProduct(e, index)}
options={
items
}
/>