Search code examples
javascriptreactjsuse-state

How can I call "useSate(false)" in React from a nested component?


How can I call "useSate(false)" in React from a nested component? I would like to close the sidebar when one of the sidebar items is clicked. For that I need to call the onclick function setOpen(true) from the parent component.

function SearchDropdown() {

    const [open, setOpen] = useState(false);

    return (
    <>
        <div className="searchIcon" onClick={() => setOpen(!open)}><img src="./assets/img/SearchN.jpg" alt=" " /><p>Search</p></div>
        {open && <>
            <div className="searchBarDropdown"><SearchBar></SearchBar></div>
            <div onClick={() => setOpen(!open)} className="searchBarDropdownX"></div>
        </>}
    </>
    );
}

function MenuSidebar() {

    const [open, setOpen] = useState(false);

    return (
    <>
        <div className="logo" onClick={() => setOpen(true)}><p>LOgo</p><img className="dropdown" src="./assets/img/Dropdown.png" alt=">" /></div>
        {open && <>
            <div className="menuSidebar">
                <h3 className="backwardsSection" onClick={() => setOpen(false)}>🠔 Go Back</h3>
                <MenuSidebarItems />
                <h3 className="sidebarTopics">Topics</h3>
                <TopicItems />
            </div>
            <div className="menuSidebarSpacing" onClick={() => setOpen(false)}></div>
        </>}
    </>
    );
}

function MenuSidebarItems() {
    return (
        <>
        <MenuSidebarItem leftIcon={ <HomeIcon /> } rightIcon={ <HomeIcon></HomeIcon> }>Home</MenuSidebarItem>
        <MenuSidebarItem leftIcon={ <HomeIcon /> }>Dashboard</MenuSidebarItem>
        <MenuSidebarItem leftIcon={ <HomeIcon /> }>Shop</MenuSidebarItem>
        <MenuSidebarItem leftIcon={ <HomeIcon /> } rightIcon={ <HomeIcon></HomeIcon> }>Projects</MenuSidebarItem>
        <MenuSidebarItem leftIcon={ <HomeIcon /> }>About</MenuSidebarItem>
        </>
    );
}

function MenuSidebarItem(props) {
    const navigate = useNavigate();
    return (
        <button className="menuItem" onClick={() => {
            navigate("/" + props.children.toString().toLowerCase());
        }}>
            <span className="leftIcon">{props.leftIcon}</span>
            {props.children}
            <span className="rightIcon">{props.rightIcon}</span>
        </button>
    );
}

Thanks, Martin


Solution

  • You need to pass the setState that close the navbar as props to the component that display the menu.

        function SearchDropdown() {
        
            const [open, setOpen] = useState(false);
        
            return (
            <>
                <div className="searchIcon" onClick={() => setOpen(!open)}><img src="./assets/img/SearchN.jpg" alt=" " /><p>Search</p></div>
                {open && <>
                    <div className="searchBarDropdown"><SearchBar></SearchBar></div>
                    <div onClick={() => setOpen(!open)} className="searchBarDropdownX"></div>
                </>}
            </>
            );
        }
        
        function MenuSidebar() {
        
            const [open, setOpen] = useState(false);
        
            return (
            <>
                <div className="logo" onClick={() => setOpen(true)}><p>LOgo</p><img className="dropdown" src="./assets/img/Dropdown.png" alt=">" /></div>
                {open && <>
                    <div className="menuSidebar">
                        <h3 className="backwardsSection" onClick={() => setOpen(false)}>🠔 Go Back</h3>
                        <MenuSidebarItems setOpen={setOpen}/>
                        <h3 className="sidebarTopics">Topics</h3>
                        <TopicItems />
                    </div>
                    <div className="menuSidebarSpacing" onClick={() => setOpen(false)}></div>
                </>}
            </>
            );
        }
        
        function MenuSidebarItems(props) {
    const {setOpen} = props
            return (
                <>
                <MenuSidebarItem setOpen={setOpen} leftIcon={ <HomeIcon /> } rightIcon={ <HomeIcon></HomeIcon> }>Home</MenuSidebarItem>
                <MenuSidebarItem setOpen={setOpen} leftIcon={ <HomeIcon /> }>Dashboard</MenuSidebarItem>
                <MenuSidebarItem setOpen={setOpen} leftIcon={ <HomeIcon /> }>Shop</MenuSidebarItem>
                <MenuSidebarItem setOpen={setOpen} leftIcon={ <HomeIcon /> } rightIcon={ <HomeIcon></HomeIcon> }>Projects</MenuSidebarItem>
                <MenuSidebarItem setOpen={setOpen} leftIcon={ <HomeIcon /> }>About</MenuSidebarItem>
                </>
            );
        }
        
        function MenuSidebarItem(props) {
            const navigate = useNavigate();
    const {setOpen}  = props
            return (
                <button className="menuItem" onClick={() => {
                   setOpen={flase}
                    navigate("/" + props.children.toString().toLowerCase());
                }}>
                    <span className="leftIcon">{props.leftIcon}</span>
                    {props.children}
                    <span className="rightIcon">{props.rightIcon}</span>
                </button>
            );
        }