skip to Main Content

I am able to close the HeadlessUI Menu component when I call the function through onScroll event within the child component but when I am passing it to the parent component and calling the same function through onScroll method in parent component, it’s not working as its meant to be, please can someone spare some time to have a look where is the error. I need to make it work; I am struggling with this since weeks.

enter image description here

/* Parent Component */
import { useRef } from 'react'
import SidebarMenuElement from '@/Layouts/Authenticated/Partials/Sidebar/MenuElement'

export default function Sidebar() {
    const sidebarMenuElementRef = useRef()

    return (
        <>
            <div>
                <div
                    className="h-full w-[inherit] overflow-y-auto scroll-smooth"
                    style={{ scrollbarGutter: 'stable both-edges' }}
                    onScroll={() => sidebarMenuElementRef.current}
                >
                    <nav>
                        <div>
                            <ul>
                                {navigation.map((item, i) => (
                                    <li key={item.name}>
                                        <SidebarMenuElement
                                            data={item}
                                            ref={sidebarMenuElementRef}
                                        />
                                    </li>
                                ))}
                            </ul>
                        </div>
                    </nav>
                </div>
            </div>
        </>
    )
}

/* Child Component */
import { useRef, forwardRef, useImperativeHandle } from 'react'
import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react'
import { Link } from '@inertiajs/react'

const SidebarMenuElement = forwardRef(function SidebarMenuElement(props, ref) {
    const { data } = props

    const menuButtonElementRef = useRef(() => {})

    useImperativeHandle(ref, () => () => menuButtonElementRef.current())

    return (
        <>
            <Menu>
                {({ close }) => (
                    <>
                        <MenuButton
                            ref={() => (menuButtonElementRef.current = close)}
                        >
                            <span>
                                <data.icon />
                            </span>
                        </MenuButton>
                        <MenuItems onScroll={menuButtonElementRef.current}>
                            <MenuItem>
                                <Link />
                            </MenuItem>
                        </MenuItems>
                    </>
                )}
            </Menu>
        </>
    )
})

export default SidebarMenuElement

2

Answers


  1. use sidebarMenuElementRef.current and also check whether you are using useRef properly or not. i have made few changes, try it.

    import { useRef } from 'react';
    import SidebarMenuElement from '@/Layouts/Authenticated/Partials/Sidebar/MenuElement';
    
    export default function Sidebar() {
        const sidebarMenuElementRef = useRef();
    
        const handleScroll = () => {
            if (sidebarMenuElementRef.current) {
                sidebarMenuElementRef.current();
            }
        };
    
        return (
            <>
                <div>
                    <div
                        className="h-full w-[inherit] overflow-y-auto scroll-smooth"
                        style={{ scrollbarGutter: 'stable both-edges' }}
                        onScroll={handleScroll}
                    >
                        <nav>
                            <div>
                                <ul>
                                    {navigation.map((item, i) => (
                                        <li key={item.name}>
                                            <SidebarMenuElement
                                                data={item}
                                                ref={sidebarMenuElementRef}
                                            />
                                        </li>
                                    ))}
                                </ul>
                            </div>
                        </nav>
                    </div>
                </div>
            </>
        );
    }
    

    childComponent

    import { useRef, forwardRef, useImperativeHandle } from 'react';
    import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react';
    import { Link } from '@inertiajs/react';
    
    const SidebarMenuElement = forwardRef(function SidebarMenuElement(props, ref) {
        const { data } = props;
    
        const menuButtonElementRef = useRef();
    
        useImperativeHandle(ref, () => ({
            closeMenu: () => {
                if (menuButtonElementRef.current) {
                    menuButtonElementRef.current();
                }
            }
        }));
    
        return (
            <>
                <Menu>
                    {({ close }) => (
                        <>
                            <MenuButton
                                ref={menuButtonElementRef}
                                onClick={close}
                            >
                                <span>
                                    <data.icon />
                                </span>
                            </MenuButton>
                            <MenuItems>
                                <MenuItem>
                                    <Link />
                                </MenuItem>
                            </MenuItems>
                        </>
                    )}
                </Menu>
            </>
        );
    });
    
    export default SidebarMenuElement;
    
    Login or Signup to reply.
  2. You can stop this by stopping the propagation, which prevents the event from bubbling up the DOM tree and stops any parent handlers from being notified of the event.

    onClick={(e) => {
    e.stopPropagation();
    }}
    

    Hope this helps! If it doesn’t, please share the code base using StackBlitz.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search