[SOLVED] chackra ui accordion open when page load

Issue

This Content is from Stack Overflow. Question asked by Zachary Lordford

I try to create side menu and the accordion to open based on page URL, I developing using Nextjs. for now I got the index from 0 to 1 but accordion is not opening, each time user click on the menu will redirected them to another page, that is why I want it to read from URL.

export default function SideMenu() {
      const [accIndex, setaccIndex] = useState(0) // initially 0
      const router = useRouter();
      useEffect(() => {
        //remove /
        let url = router.pathname;
        let newUrl = url.slice(1, url.length); //remove / at the beginning
        let second = newUrl.search("/"); // search for any / in trail
        let cutUrl = second > -1 ? newUrl.slice(0, second) : newUrl;
        for (const x in Menu) {
          if (cutUrl === Menu[x].item.toLowerCase()) {
            setaccIndex(Menu[x].index); // set to 1
          }
        }
      }, []);
      
      function selectedMenu(path) {
        router.push(path);
      }
    return (
    <>
      <Accordion allowMultiple defaultIndex={[accIndex]}>
        {/* dashboard */}
        <AccordionItem>
          <AccordionButton
            className="my-box"
            onClick={() => selectedMenu("/dashboard")}
          >Dashboard
          </AccordionButton>
        </AccordionItem>
        {/* dashboard  end*/}

        {/* about */}
        <AccordionItem>
          <AccordionButton>
            about
            <AccordionIcon />
          </AccordionButton>
          <AccordionPanel>
            {/* company 1 */}
            <AccordionItem>
              <AccordionButton onClick={() => selectedMenu("/com/company1")}>
                company 1
              </AccordionButton>
            </AccordionItem>
            {/* company 1 end*/}
          </AccordionPanel>
        </AccordionItem>
     </Accordion>
     </>



Solution

Try to use index instead of default index. It doesn’t make sense to have allowMultiple here, as that would mean you would have more than one accordion item open but only one will be reflected in the url.

You can use useMemo instead of the useEffect:

      const router = useRouter();
      const index = useMemo(() => {
        //remove /
        let url = router.pathname;
        let newUrl = url.slice(1, url.length); //remove / at the beginning
        let second = newUrl.search("/"); // search for any / in trail
        let cutUrl = second > -1 ? newUrl.slice(0, second) : newUrl;
        for (const x in Menu) {
          if (cutUrl === Menu[x].item.toLowerCase()) {
            return Menu[x].index; // set to 1
          }
        }
        return 0; //default return, could be something else
      }, []);
   
      ....

      
    return (
    <>
      <Accordion index={index}>


This Question was asked in StackOverflow by Zachary Lordford and Answered by Asen Mitrev It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?