React - Expand/Collapse All

18,081

In the collapsible panel you are toggling the previous state. Instead you have to explicitly set expand/collapse state..

  const animate = collapse => {
    setIsCollapse(collapse);
    setIcon(state => {
      return state === "fa fa-chevron-down"
        ? "fa fa-chevron-right"
        : "fa fa-chevron-down";
    });
  };

  useEffect(() => {
    animate(!collapse);
  }, [collapse]);

Try the below sandbox.

https://codesandbox.io/s/festive-moore-cbqsn

Share:
18,081
kabeer rifaye
Author by

kabeer rifaye

Updated on June 04, 2022

Comments

  • kabeer rifaye
    kabeer rifaye almost 2 years

    I would like to Expand/Collapse all using a single button click.

    Created a new component CollapsiblePanel using reactstrap and using the created component in the container(index.js).

    Now I can able to expand/collapse all the containers on clicking the button.

    https://codesandbox.io/s/fervent-banzai-s9pst

    CollapsiblePanel.js

    import React, { useState, useEffect } from "react";
    import { Collapse } from "reactstrap";
    
    function CollapsiblePanel({ children, ...props }) {
        const { title, collapse } = props;
        const [isCollapse, setIsCollapse] = useState(collapse);
        const [icon, setIcon] = useState("fa fa-chevron-down");
        const toggle = () => {
            setIsCollapse(!isCollapse);
            setIcon(state => {
                return state === "fa fa-chevron-down"
                    ? "fa fa-chevron-right"
                    : "fa fa-chevron-down";
            });
        };
    
        useEffect(() => {
            toggle();
        }, [collapse]);
    
        return (
            <div className="coll-panel">
                <button
                    type="button"
                    className="coll-panel-btn btn-primary btn-block text-left"
                    onClick={() => toggle()}
                >
                    <i className={icon} /> {title}
                </button>
                <Collapse className="border text-left p-2" isOpen={isCollapse}>
                    {children}
                </Collapse>
            </div>
        );
    }
    
    CollapsiblePanel.defaultProps = {
        children: "Add node as a child",
        title: "Collapsible Panel",
        collapse: true
    };
    
    export default CollapsiblePanel;
    

    index.js

    import React, { useState } from "react";
    import ReactDOM from "react-dom";
    import CollapsiblePanel from "./component/CollapsiblePanel";
    
    import "../node_modules/bootstrap/dist/css/bootstrap.min.css";
    import "./styles.css";
    
    function App() {
        const text =
            "Lorem ipsum dolor sit amet consectetur adipisicing elit.Nihil earum illo ipsa velit facilis provident qui eligendi, quia ut magnam tenetur. Accusantium nisi quos delectus in necessitatibus ad. Ducimus, id!";
        const [collapse, setCollapse] = useState(true);
        const [title, setTitle] = useState("Expand All");
        const [icon, setIcon] = useState("fa fa-chevron-right");
        const collapseAll = () => {
            setCollapse(!collapse);
            setIcon(state => {
                return state === "fa fa-chevron-right"
                    ? "fa fa-chevron-down"
                    : "fa fa-chevron-right";
            });
            setTitle(state => {
                return state === "Expand All" ? "Collapse All" : "Expand All";
            });
        };
        return (
            <div className="App container my-2">
                {/* Expand/Collapse All */}
                <button
                    type="button"
                    className="btn-warning mt-4 mb-3 float-left"
                    onClick={collapseAll}
                >
                    <i className={icon} /> {title}
                </button>
                <CollapsiblePanel title="Title 1" collapse={collapse}>
                    <span>{text}</span>
                </CollapsiblePanel>
                <CollapsiblePanel title="Title 2" collapse={collapse}>
                    <span>{text}</span>
                </CollapsiblePanel>
                <CollapsiblePanel title="Title 3" collapse={collapse}>
                    <span>{text}</span>
                </CollapsiblePanel>
                <CollapsiblePanel title="Title 4" collapse={collapse}>
                    <span>{text}</span>
                </CollapsiblePanel>
                <CollapsiblePanel title="Title 5" collapse={collapse}>
                    <span>{text}</span>
                </CollapsiblePanel>
            </div>
        );
    }
    

    Now: Before clicking the Expand/Collapse All button, If any of the collapsible containers (in index.js) is clicked and then on clicking the Expand/Collapse button not all the containers are expanding.

    The opened is closing and vice versa.

    Expected:

    Though the container is opened/closed explicitly. On clicking the Expand/Collapse I would like to expand/collapse all. Thanks in advance.