How to create collapse expand list in react

后端 未结 2 1249
春和景丽
春和景丽 2021-01-17 03:17

I try to create a collapse and expand side menu in React (v 16.5) with the following criteria -

On page load first item (Circulars) will be in expanded

相关标签:
2条回答
  • 2021-01-17 03:33

    To do that I would use React.useState, since its a small state to control and to animate I would use CSS:

    The component would look like this:

    function SidebarNavs() {
      const [activeItem, setActiveItem] = React.useState(1);
    
      return (
        <div className="sidebar-nav">
          <div className="sidebar-nav-menu">
            <SidebarItem
              title="Circulars"
              setActiveItem={setActiveItem}
              index={1}
              activeItem={activeItem}
            >
              Sidebar Content Here
            </SidebarItem>
    
            <SidebarItem
              title="Specifications"
              setActiveItem={setActiveItem}
              index={2}
              activeItem={activeItem}
            >
              Sidebar Content Here
            </SidebarItem>
    
            <SidebarItem
              title="Specifications"
              setActiveItem={setActiveItem}
              index={3}
              activeItem={activeItem}
            >
              Work Orders
            </SidebarItem>
          </div>
        </div>
      );
    }
    
    function SidebarItem({ title, children, setActiveItem, activeItem, index }) {
      const expanded = activeItem === index;
      const cls = "sidebar-nav-menu-item " + (expanded ? "item-active" : "");
      return (
        <div className={cls}>
          <div className="sidebar-nav-menu-item-head">
            <div className="sidebar-nav-menu-item-head-title">{title}</div>
            <div className="sidebar-nav-menu-item-head-help">
              <button
                type="button"
                className="btn-help"
                onClick={() => setActiveItem(index)}
              >
                View more info
              </button>
            </div>
            <div className="sidebar-nav-menu-item-head-icon">
              <i className="fa fa-caret-down" aria-hidden="true" />
            </div>
          </div>
          <div className="sidebar-nav-menu-item-body">{children}</div>
        </div>
      );
    }
    

    The CSS would look like this:

    .sidebar-nav-menu-item {
      border: 1px solid #CCC;
      margin-bottom: 20px;
    }
    .sidebar-nav-menu-item .sidebar-nav-menu-item-body {
      overflow: hidden;
      max-height: 0;
      transition: all linear 0.5s;
    }
    
    .sidebar-nav-menu-item.item-active .sidebar-nav-menu-item-body {
      max-height: 100px;
      transition: all linear 0.5s 0.3s;
    }
    
    
    0 讨论(0)
  • 2021-01-17 03:44

    You should use a state variable to show your collapsiable item active / in-active.

    I modified your code a bit to fit it into your requirements.

    class App extends Component {
      constructor() {
        super();
        this.state = {
            activeCollapse: 'circulars'
        };
      }
    
      handleExpandCollaps = (name) => {
        if (this.state.activeCollapse === name) {
            this.setState({ activeCollapse: '' })
        } else {
            this.setState({ activeCollapse: name })
        }
      }
    
      moreInfoClick = (e) => {
        e.stopPropagation();
        console.log("clicked");
      }
      render() {
        return (
          <div>
            <div className="sidebar-nav">
              <div className="sidebar-nav-menu">
    
                <div className={`sidebar-nav-menu-item ${this.state.activeCollapse === "circulars" ? 'item-active' : ''}`} onClick={() => this.handleExpandCollaps("circulars")} data-id="circulars" >
                  <div className="sidebar-nav-menu-item-head">
                    <span className="sidebar-nav-menu-item-head-title">Circulars</span>
                    <span className="sidebar-nav-menu-item-head-help">
                      <button type="button" className="btn-help" onClick={this.moreInfoClick}>View more info</button>
                    </span>
                  </div>
                  <div className="sidebar-nav-menu-item-body">BODY CONTENT HERE</div>
                </div>
    
                <div className={`sidebar-nav-menu-item ${this.state.activeCollapse === "specifications" ? 'item-active' : ''}`} onClick={() => this.handleExpandCollaps("specifications")} data-id="specifications">
                  <div className="sidebar-nav-menu-item-head">
                    <span className="sidebar-nav-menu-item-head-title">Specifications</span>
                    <span className="sidebar-nav-menu-item-head-help">
                      <button type="button" className="btn-help" onClick={this.moreInfoClick}>View more info</button>
                    </span>
                  </div>
                  <div className="sidebar-nav-menu-item-body">BODY CONTENT HERE</div>
                </div>
    
    
                <div className={`sidebar-nav-menu-item ${this.state.activeCollapse === "wo" ? 'item-active' : ''}`} onClick={() => this.handleExpandCollaps("wo")} data-id="wo">
                  <div className="sidebar-nav-menu-item-head">
                    <span className="sidebar-nav-menu-item-head-title">Work Orders</span>
                    <span className="sidebar-nav-menu-item-head-help">
                      <button type="button" className="btn-help" onClick={this.moreInfoClick}>View more info</button>
                    </span>
                  </div>
                  <div className="sidebar-nav-menu-item-body">BODY CONTENT HERE</div>
                </div>
    
              </div>
            </div>
          </div>
        );
      }
    }
    

    Note: I have used CSS for font-awesome icons. Hope you have added font-awesome

    Demo

    0 讨论(0)
提交回复
热议问题