Reputation: 485
I'm mapping over each object inside the array of objects inside my state's item property. The issue is, I want to be able to attach a button to each returned item that only works with that item, and not the other items too. Here's what I have so far:
class App extends React.Component {
state = {
item: [],
}
componentDidMount() {
this.setState({
item: [
{
name: 'jacob',
hair: 'brown',
sex: 'male',
}, {
name: 'hannah',
hair: 'brown',
sex: 'female',
}
]
})
}
handleChange = (e) => {
console.log(e.target.value)
var x = Object.assign({}, this.state)
}
render() {
return(
<div>
{ this.state.item.length > 0 ?
(
<div className="row mt-5">
<Item item={ this.state.item } handleChange={ this.handleChange } />
</div>
) : null
}
</div>
)
}
}
class Item extends React.Component {
render() {
return(
<div className="col">
{ this.props.item.map(s => (
<div>
<div className="mt-5">{ s.name }</div>
<button onClick={ this.props.handleChange } value={ s.name }>Click</button>
</div>
))}
</div>
)
}
}
So for instance, if the button's fx was to change the name property of the item it was rendered with, I want it to only change that item and no other items should be affected. Whenever I iterate through it attaches the button's fx to every item, so if I click it for one, I'm really clicking it for all of them, and that's exactly what I don't want.
For those curious, I'm setting the state in componentDidMount to simulate calling an API.
Also, the fx that's currently running in the handleChange is just some messing around I was doing trying to figure out values and a solution to manipulating a nested object inside an array.
Upvotes: 1
Views: 4078
Reputation: 1342
Try this refactored code on CodeSandBox, You have to add keys when iterating Components in React, i've added it, also the Item Component could be function Component since it doesn't handle a state.
Updated: below is the code in case it wouldn't be available on codesandbox.
import React from 'react';
import { render } from 'react-dom';
class App extends React.Component {
state = {
items: [],
}
componentDidMount() {
this.setState({
items: [
{
name: 'jacob',
hair: 'brown',
sex: 'male',
}, {
name: 'hannah',
hair: 'brown',
sex: 'female',
}
]
})
}
handleChange = (e) => {
console.log(e.target.value)
}
render() {
const { items } = this.state;
return (
<div>
{items.length && (
items.map((item, index) => (
<div className="row mt-5" key={index}>
<Item item={item} handleChange={this.handleChange} />
</div>
))
)
}
</div>
)
}
}
const Item = ({ item, handleChange }) => (
<div className="col">
<div className="mt-5">{item.name}</div>
<button onClick={handleChange} value={item.name}>Click</button>
</div>
);
render(<App />, document.getElementById('root'));
Upvotes: 1
Reputation: 4473
I think you want to pass the individual element in to your handleChange
:
{ this.props.item.map((s, i) => {
<div>
<div className="mt-5">{ s.name }</div>
<button key={i} onClick={ (s) => this.props.handleChange(s) } value={ s.name }>Click</button>
</div>
})}
This way, you will have the individual item
passed in as an argument, so when you are writing your handleChange
, you can do whatever you want with just that item and not the whole array.
Upvotes: 1