Apply changes only to the clicked element of multiple elements with the same method name
I have several divs that show various details. I intended to take data from the backend and link it to my html part. So far I have hardcoded the details. This is my html part
<div className="trait_box polaroid" onClick={this.trait_select}>
<div className="main_trait_card" style={{transform: this.state.rotated ? 'rotateY(180deg)' : 'none' }}>
<div className="front_card_rotate">
<div className="trait_description_div">
<span className="trait_description">Honesty</span>
</div>
<div className="trait_img_div">
<img src={Honesty} className="trait_img"/>
</div>
<div className="block__body">
<img src={Add} className="trait_add"/>
<p className="trait_text">Honesty refers to a facet of moral character and connotes positive and virtuous attributes such as integrity, truthfulness,straightforwardness etc.. </p>
</div>
</div>
<div className="back_card_rotate front_card_rotate">
<span>Wolverine</span>
</div>
</div>
</div>
This is a div that will repeat based on the number of elements in the backend.
I rotate these divs onClick like this
constructor() {
super();
this.state = {rotated: false};
this.trait_select = this.trait_select.bind(this);
}
trait_select = (e) => {
this.setState({rotated: !this.state.rotated});
}
My problem is the same css classes are repeated when there is more than 1 element, rotate each time when I click on the element. Because every element has the same css classes. How can I tell the difference between the element I click on other elements?
source to share
I think each trait_box should be a component and manage your own state:
class TraitBox extends Component {
constructor(props) {
super(props);
this.state = { rotate: false }
}
trait_select = (e) => {...}
render() {
return ( <div className="trait_box..." ></div> )
}
}
// and then you can import/use that component in a container
class ContainerApp extends Component {
render() {
return (
<TraitBox />
<TraitBox />
<TraitBox />
)
}
}
Now each TraitBox can manage your own state and styles
Btw, you don't need this:
this.trait_select = this.trait_select.bind(this);
if trait_select is an arrow function (AF should automatically bind "this").
source to share
Replace boolean with an array and use e.target.name
to identify the clicked property:
constructor() {
super();
this.state = { rotated_traits: [] };
this.trait_select = this.trait_select.bind(this);
}
trait_select = (e) => {
const rotated_traits = this.state.rotated_traits
rotated_traits[e.target.name] = !this.state.rotated_traits[e.target.name]
this.setState({ rotated_traits });
}
and
<div className="trait_box polaroid" name={trait.id} onClick={this.trait_select}>
<div className="main_trait_card" style={{transform: this.state.rotated_traits[trait.id] ? 'rotateY(180deg)' : 'none' }}>
..
</div>
</div>
If you haven't trait.id
, you can use index
:
traits.map((trait, index) =>
...
)
source to share