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.