Search code examples
javascriptreactjsreact-hooks

Table Accordion in React JS


I want to make table accordion .when I clicked on table row the next table data should display by default first one should be open and when I click another header there content should open without closing previous one.

I have created the state:

const [active, setActive] = useState(false);
  const handleClick = () => {
    setActive(!active);
  };
  return (
    <div>
      <div>
        <table className="table border">
          <tr>
            <td colSpan={3} className="header" onClick={handleClick}>
              Winfield
            </td>
          </tr>
          {active && (
            <tr>
              <td>USJN - Tifton </td>
              <td>12 </td>
              <td> 800</td>
            </tr>
          )}

          <tr>
            <td colSpan={3} className="header" onClick={handleClick}>
              Helena
            </td>
          </tr>
          {active && (
            <tr>
              <td>USJN - Tifton USJN - Tifton USJN - Tifton USJN - Tifton </td>
              <td>12 </td>
              <td> 800</td>
            </tr>
          )}
        </table>
      </div>
    </div>
  );

Solution

  • One way would be to extract the accordion row into it's own separate component. This will allow you to have separates states for each row.

    function CollapsibleRow({ data, defaultIsOpen = false, children }) {
      const [isOpen, setIsOpen] = React.useState(defaultIsOpen);
    
      return (
        <React.Fragment>
          <tr>
            <td colSpan={3} className="header" onClick={() => setIsOpen(!isOpen)}>
              {data}
            </td>
          </tr>
          {isOpen && children}
        </React.Fragment>
      );
    }
    
    function App() {
      return (
        <div>
          <div>
            <table>
              <tbody>
                <CollapsibleRow data="Winfield" defaultIsOpen={true}>
                  <tr>
                    <td>USJN - Tifton </td>
                    <td>12 </td>
                    <td> 800</td>
                  </tr>
                </CollapsibleRow>
                <CollapsibleRow data="Helena">
                  <tr>
                    <td>
                      USJN - Tifton USJN
                    </td>
                    <td>12 </td>
                    <td> 800</td>
                  </tr>
                </CollapsibleRow>
              </tbody>
            </table>
          </div>
        </div>
      );
    }
    
    ReactDOM.render(<App />, document.getElementById("root"));
    table {
      table-layout: fixed;
      width: 100%;
      border-collapse: collapse;
    }
    
    td {
      border: 1px solid #ccc;
      padding: 0.5rem;
    }
    <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <div id="root"></div>