Dependencies:
- Nextjs v15
- Reactjs v18
- Prime React v10.8.5(UI Lib)
- Typescrpt
- Prime Flex
Problem:
I made a basic hamburger menu with prime react components, I want to add a loading animation when a route is clicked, then when a new route is loaded the animation should stop.
Code:
Below you will see two files that have this set up however the loading animation is being triggered when opening the menu instead of when clicking a route. I’ve tried a few different methods and cant seem to figure out a working one
<MenuModel/>
Hamburger Parent Component
'use client';
import { Button } from 'primereact/button';
import { Sidebar } from 'primereact/sidebar';
import { useState } from 'react';
import { MobileMenu } from './MobileMenu';
import LoadMask from '../LoadMask';
import SVGBackground from '../backgrounds/svg/SVGBackground';
export const MenuModel = () => {
const [visible, setVisible] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const onClose = () => {
if (!isLoading && visible) {
setVisible(false);
setIsLoading(true);
}
};
return (
<>
<Button
icon={'fa-solid fa-bars'}
onClick={() => setVisible(true)}
style={{
position: 'fixed',
top: '2rem',
right: '2rem',
padding: '5px',
zIndex: 999,
}}
pt={{
root: {
style: {
backgroundColor: 'white',
},
},
}}
/>
<Sidebar
visible={visible}
onHide={() => setVisible(false)}
position='right'
className='flex justify-content-center align-content-center sideMenu bg-black-alpha-90'
closeIcon={
<i
className='fa-solid fa-xmark fa-lg cursor-pointer hover:shadow-4'
style={{ color: 'white', zIndex: 999 }}
/>
}
>
<MobileMenu onClose={onClose} />
<LoadMask loading={isLoading} /> //this is a typical load mask and shows when true
</Sidebar>
</>
);
};
<MobileMenu/>
– shows when hamburger menu is open
import { useRouter } from 'next/navigation';
import { Ripple } from 'primereact/ripple';
import XYButton from '../Inputs/XYButton'; // same as prime react <Button/>
const BUTTON_SYLE = 'p-2 font-bold w-11';
interface MenuItem {
label: string;
route: string;
}
interface MobileMenuProps {
onClose: () => void;
}
export const MobileMenu = ({ onClose }: MobileMenuProps) => {
const currentRoute = window.location.pathname;
const router = useRouter();
const handleNavigateClick = (to: string) => {
router.push(`/${to}`);
onClose();
};
const MENU: MenuItem[] = [
{ label: 'Home', route: '' },
{
label: 'Project Gallery',
route: 'projectGallery',
},
{
label: 'Our Team',
route: 'team',
},
{
label: 'About XYS',
route: 'about',
},
{
label: 'Client Portal',
route: 'login',
},
{
label: 'Privacy & Terms',
route: 'privacy',
},
];
function filterMenuByLabel(
menu: MenuItem[],
labelToRemove: string
): MenuItem[] {
return menu.filter(
(item) => item.route !== labelToRemove.replace('/', '')
);
}
const MENU_WITHOUT_CURRENT_ROUTE: MenuItem[] = filterMenuByLabel(
MENU,
currentRoute
);
return (
<div className='flex flex-column p-1 mobileMenu gap-4 justify-content-center align-content-center'>
{MENU_WITHOUT_CURRENT_ROUTE.map((page) => {
return (
<div
key={page.route}
className='flex justify-content-center align-items-center'
>
<XYButton
key={page.route + '-x'}
className={BUTTON_SYLE}
label={page.label}
onClick={() => handleNavigateClick(page.route)}
xyType='transparentWhite'
>
<Ripple
pt={{
root: {
style: {
background: 'rgba(0, 14, 0, .4)',
},
},
}}
/>
</XYButton>
</div>
);
})}
</div>
);
};