Skip to content
Advertisement

onClick of button triggering all the components to open – Reactjs

I implemented a Card component and basically generating a bunch of cards on some input data. I binded a setter function on button click on every card which basically expands and collapse it. Even after putting unique keys to the div is sort of triggering all the cards to open at once.

Here is the code piece:

import React, { useState } from 'react';

import PrettyPrintJson from './PrettyPrintJson';
import './Card.scss';
import '../App.scss';

const Card = (props) => {
    const { data } = props;
    const [collapse, toggleCollapse] = useState(true);

    return (<div className="card-group">
    {data.map((obj, idx)=>{
        return <div className="card" key={`${idx}_${obj?.lastModifiedOn}`}>
        <div className="card-header">
            <h4 className="card-title">{`fId: ${obj?.fId}`}</h4>
            <h6 className="card-title">{`name: ${obj?.name}`}</h6>
            <h6 className="card-title">{`status: ${obj?.status}`}</h6>
            <div className="heading-elements">
                <button className="btn btn-primary" onClick={() => toggleCollapse(!collapse)}>Show Json</button>
            </div>
        </div>
        <div className={`card-content ${!collapse ? 'collapse show' : 'collapsing'}`}>
            <div className="card-body">
                <div className="row">
                <PrettyPrintJson data={ obj } />
                </div>
            </div>
        </div>
    </div>
    })}
    </div>
    );
}

export default Card;

Advertisement

Answer

Create a component that manages it’s own state and render that component.

const CardItem = ({ obj }) => {

  const [collapse, toggleCollapse] = useState(true);

  return (<div className="card">
  <div className="card-header">
      <h4 className="card-title">{`fId: ${obj?.fId}`}</h4>
      <h6 className="card-title">{`name: ${obj?.name}`}</h6>
      <h6 className="card-title">{`status: ${obj?.status}`}</h6>
      <div className="heading-elements">
          <button className="btn btn-primary" onClick={() => toggleCollapse(!collapse)}>Show Json</button>
      </div>
  </div>
  <div className={`card-content ${!collapse ? 'collapse show' : 'collapsing'}`}>
      <div className="card-body">
          <div className="row">
          <PrettyPrintJson data={ obj } />
          </div>
      </div>
  </div>
</div>)
}

then render it like

{data.map((obj, idx)=> (<CardItem obj={obj} key={idx} />))}
Advertisement