Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Problem using shared Layout for menu in React-Router-DOM v6

I am trying to build an APP in which the side menu items will be different on different page Layouts. I do not want to hardcode the link instead trying to make it reusable. But the menu is not expanding when wrapping it with the react-router-dom.

TestMenuAccordion.tsx:

import { useState } from "react";

const Accordion = ({
  controllerElement,
  contentDescription,
  children,
}: any) => {
  const [isExpanded, setIsExpanded] = useState(false);

  return (
    <div className="w-full mt-4">
      <div
        aria-expanded={isExpanded}
        aria-controls={contentDescription}
        aria-label={(isExpanded ? "hide " : "show ") + contentDescription}
        onClick={() => setIsExpanded((prevIsExpanded) => !prevIsExpanded)}
      >
        {controllerElement(isExpanded)}
      </div>
      {isExpanded && (
        <div id={contentDescription} className="w-full">
          {children}
        </div>
      )}
    </div>
  );
};

export default Accordion;

TestMenu.tsx

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

import Accordion from "./TestMenuAccordion";
// import "./SideNav.css";
import { Link } from "react-router-dom";

export function SideNavEx(
  props: any,
  { children }: { children: React.ReactNode },
) {
  return (
    <Accordion
      controllerElement={(isExpanded: any) => (
        <button className={isExpanded ? "selected" : "not-selected"}>
          {props.label} {isExpanded ? "-" : "+"}
        </button>
      )}
      contentDescription="menu items"
    >
      <ul className="sideNav">{children}</ul>
    </Accordion>
  );
}

export function GeneralMenuItems(props: any) {
  return (
    <Link to={props.url}>
      <li>{props.text}</li>
    </Link>
  );
}

PageLayout.tsx

import { Outlet } from "react-router-dom";
import { SideNavEx, GeneralMenuItems } from "./TestMenu";

const PageLayout = () => {
  return (
    <>
      <section className="container pt-5 pb-40 px-4 mx-auto grid md:px-8 md:grid-cols-10 md:text-left">
        <div className="px-4 col-span-10 md:col-span-5 lg:col-span-3">

          <SideNavEx label={"General side Menu "}>
            <GeneralMenuItems url={"/Generalmenu1"} text={"Genetal Item 1"} />
            <GeneralMenuItems url={"/Generalmenu2"} text={"Genetal Item 2"} />
            <GeneralMenuItems url={"/Generalmenu3"} text={"Genetal Item 3"} />
          </SideNavEx>

        </div>
        <div className="px-4 pt-4 col-span-10 md:col-span-5 lg:col-span-7">
          <Outlet />
        </div>
      </section>
    </>
  );
};

export default PageLayout;

I am working with React version 18.2 and React-Router-DOM version 6.21.

>Solution :

It would seem you have mis-declared the SideNavEx component. React components take a single props object, but you have declared that SideNavEx takes two arguments.

Based on the usage it seems you should just remove the first arg, props: any, leaving a single props object with a destructured children prop typed as React.ReactNode, and add the missing label prop.

export function SideNavEx(
  { children, label }: { children: React.ReactNode; label: string }
) {
  return (
    <Accordion
      controllerElement={(isExpanded: boolean) => (
        <button className={isExpanded ? "selected" : "not-selected"}>
          {label} {isExpanded ? "-" : "+"}
        </button>
      )}
      contentDescription="menu items"
    >
      <ul className="sideNav">{children}</ul>
    </Accordion>
  );
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading