I have an object in state ("car") with multiple keys, one of which is an array ("features"). There's a couple things I'm trying to do with it.
I've researched this online quite a bit and haven't found anything (maybe because this isn't possible). Either way, here's my code:
class Car extends React.Component {
state = {
car: {make: 'Toyota', model: 'Camry', features: []},
}
handleChange = (e, index) => {
const value = e.target.value
let features = this.state.car.features.slice() // create mutable copy of array
features = features[index].concat(value)
this.setState({...this.state.car, features: features})
}
handleAddFeature = () => {
let features = this.state.car.features.slice()
features.push('')
this.setState({...this.state.car, features: features})
}
render() {
return (
{
this.state.car.features.map((f, index) => { return <input key={index} onChange={e => this.handleChange(e, index)}>{feature}</input>
}
<button onClick={this.handleAddFeature}>Add Feature</button>
)
}
}
Okay, I got this working in a very similar way to @Snkendall's answer. My handleChange
function is listed below:
handleChange = (e, index,) => {
let array = this.state.car.features.slice() // create mutable copy of the array
array[index] = e.target.value // set the value of the feature at the index in question to e.target.value
const newObj = { ...this.state.car, features: array } // create a new object by spreading in the this.state.car and overriding features with our new array
this.setState({ car: newObj }) // set this.state.car to our new object
}
The difference between this solution and @Snkendall's is the defining of a newObj
variable. That turns out to the be the only way to update an individual key nested inside a state object.
Ad.1
handleAddFeature = () => {
const car = this.state.car
car.features.push('Your feature')
this.setState({ car })
}
Just create copy and push to car features new value.
Ad. 2 Create component called eg Feature. He will have own state where you modify string and through props you can extract data to your "car".
There are a few things that could be causing you problems... if your component has a state, you should use a constructor, and bind your 'this' references inside it to prevent 'this' from referencing the global. You just wrap your state like this:
class Car extends React.Component {
constructor() {
super()
this.state = {
car: {make: 'Toyota', model: 'Camry', features: []},
}
this.handleChange = this.handleChange.bind(this)
this.handleAddFeature = this.handleAddFeature.bind(this)
}
This is a really great article for thinking about 'this': http://2ality.com/2017/12/alternate-this.html
Another area that might cause you problems is features = features[index].concat(value)
... because you're concatting the input tag's value onto the current string on state over and over again with every change (keystroke). You can just reset the value of the element at that index in the array like this:
handleChange = (e, index) => {
const value = e.target.value
let features = this.state.car.features.slice()
features[index] = value
this.setState({...this.state.car, features})
}
and that way, each keystroke just resets the value on state to reflect the change created in the input. You actually wouldn't need to use the handleAddFeature at all, since the state is already updated with handleChange.
I'm changing features:features
to just features
because ES6 destructuring has this fun thing where if a key and it's value is the same, you only need to reference it once, and it figures it out. It's just a cool way to keep your code even DRYer.
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.