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?

+3


source to share


2 answers


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").

+1


source


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) =>
  ...
)

      

0


source







All Articles