You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+ChakraUI中点击Links组件时Drawer的onClose失效问题

问题描述

使用HorizonUI模板结合ChakraUI与ReactJS开发,给Navbar组件添加了Drawer,在Drawer主体中调用Links组件。目前点击关闭按钮或Drawer外部可正常关闭Drawer,但点击Links组件内的导航链接时,无法触发onClose关闭Drawer。

当前Drawer中Links组件的调用代码:

<Links routes={routes} onClick={onClose}/>
import Links from "components/sidebar/components/Links";
export default function AdminNavbar(props) {
    const { isOpen, onOpen, onClose } = useDisclosure()
    const { secondary, brandText } = props;
    let mainText = useColorModeValue('navy.700', 'white');
    let navbarPosition = 'fixed';
    let navbarFilter = 'none';
    let navbarBackdrop = 'blur(20px)';
    let navbarShadow = 'none';
    let navbarBg = useColorModeValue('rgba(244, 247, 254, 0.2)', 'rgba(11,20,55,0.5)');
    let navbarBorder = 'transparent';
    let secondaryMargin = '0px';
    let gap = '0px';
    return (
        <Box
            position={navbarPosition}
            boxShadow={navbarShadow}
            bg={navbarBg}
            borderColor={navbarBorder}
            filter={navbarFilter}
            backdropFilter={navbarBackdrop}
            backgroundPosition='center'
            backgroundSize='cover'
            borderRadius='16px'
            alignItems={{ xl: 'center' }}
            display={secondary ? 'block' : 'flex'}
            minH='50px'
            justifyContent={{ xl: 'center' }}
            lineHeight='25.6px'
            mx='auto'
            mt={secondaryMargin}
            top={{ base: '12px', md: '16px', lg: '20px', xl: '20px' }}
            right={{ base: '500px' }}
            left={{ base: '500px' }}
            
            onClick={onOpen}
            >
            <Flex
                alignItems={{ xl: 'center' }}
                mb={gap}
            >
                <Box>
                    <Text color={mainText}
                        
                        href='#'
                        bg='inherit'
                        borderRadius='inherit'
                        fontWeight='bold'
                        fontSize='34px'
                        _hover={{ color: { mainText } }}
                        _active={{
                            bg: 'inherit',
                            transform: 'none',
                            borderColor: 'transparent'
                        }}
                        _focus={{
                            boxShadow: 'none'
                        }}
                        style={{ userSelect: "none" }}>
                            {brandText}
                        </Text>
                </Box>
            </Flex>
            <Drawer placement="top" isOpen={isOpen} onClose={onClose} size='xs' blockScrollOnMount={false}>
                <DrawerOverlay />
                <DrawerContent 
                boxShadow={navbarShadow}
                bg={navbarBg}
                borderColor={navbarBorder}
                filter={navbarFilter}
                backdropFilter={navbarBackdrop}
                backgroundPosition='center'
                backgroundSize='cover'
                borderRadius='16px'
                alignItems={{ xl: 'center' }}
                justifyContent={{ xl: 'center' }}
                lineHeight='25.6px'
                mx='auto'
                >
                <DrawerCloseButton />
                <DrawerHeader
                    color={mainText}
                    href='#'
                    fontWeight='bold'
                    fontSize='40px'
                    style={{ userSelect: "none" }}
                    onClick={onClose}>
                        Inventory SCM
                </DrawerHeader>
                <DrawerBody>
                    <Links routes={routes} onClick={onClose}/>
                </DrawerBody>
                </DrawerContent>
            </Drawer>
        </Box>      
    );
}
export function SidebarLinks(props) {
  let location = useLocation();
  let activeColor = useColorModeValue("gray.700", "white");
  let inactiveColor = useColorModeValue(
    "secondaryGray.600",
    "secondaryGray.600"
  );
  let activeIcon = useColorModeValue("brand.500", "white");
  let textColor = useColorModeValue("secondaryGray.500", "white");
  let brandColor = useColorModeValue("brand.500", "brand.400");
  const { routes } = props;
  const activeRoute = (routeName) => {
    return location.pathname.includes(routeName);
  };
  const createLinks = (routes) => {
    return routes.map((route, index) => {
      if (route.category) {
        return (
          <>
            <Text
              fontSize={"md"}
              color={activeColor}
              fontWeight='bold'
              mx='auto'
              ps={{
                sm: "10px",
                xl: "16px",
              }}
              pt='18px'
              pb='12px'
              key={index}>
              {route.name}
            </Text>
            {createLinks(route.items)}
          </>
        );
      } else if (
        route.layout === "/admin" ||
        route.layout === "/auth" ||
        route.layout === "/rtl"
      ) {
        return (
          <NavLink key={index} to={route.layout + route.path}>
            {route.icon ? (
              <Box>
                <HStack
                  spacing={
                    activeRoute(route.path.toLowerCase()) ? "22px" : "26px"
                  }
                  py='5px'
                  ps='10px'>
                  <Flex w='100%' alignItems='center' justifyContent='center'>
                    <Box
                      color={
                        activeRoute(route.path.toLowerCase())
                          ? activeIcon
                          : textColor
                      }
                      me='18px'>
                      {route.icon}
                    </Box>
                    <Text
                      me='auto'
                      color={
                        activeRoute(route.path.toLowerCase())
                          ? activeColor
                          : textColor
                      }
                      fontWeight={
                        activeRoute(route.path.toLowerCase())
                          ? "bold"
                          : "normal"
                      }>
                      {route.name}
                    </Text>
                  </Flex>
                  <Box
                    h='36px'
                    w='4px'
                    bg={
                      activeRoute(route.path.toLowerCase())
                        ? brandColor
                        : "transparent"
                    }
                    borderRadius='5px'
                  />
                </HStack>
              </Box>
            ) : (
              <Box>
                <HStack
                  spacing={
                    activeRoute(route.path.toLowerCase()) ? "22px" : "26px"
                  }
                  py='5px'
                  ps='10px'>
                  <Text
                    me='auto'
                    color={
                      activeRoute(route.path.toLowerCase())
                        ? activeColor
                        : inactiveColor
                    }
                    fontWeight={
                      activeRoute(route.path.toLowerCase()) ? "bold" : "normal"
                    }>
                    {route.name}
                  </Text>
                  <Box h='36px' w='4px' bg='brand.400' borderRadius='5px' />
                </HStack>
              </Box>
            )}
          </NavLink>
        );
      }
    });
  };
  return createLinks(routes);
}
export default SidebarLinks;
解决方案

问题核心是Links组件没有接收并传递onClick属性到内部的NavLink元素上。修改Links组件,让它接收onClick参数并绑定到每个导航链接即可:

修改后的Links.js代码:

export function SidebarLinks(props) {
  let location = useLocation();
  let activeColor = useColorModeValue("gray.700", "white");
  let inactiveColor = useColorModeValue(
    "secondaryGray.600",
    "secondaryGray.600"
  );
  let activeIcon = useColorModeValue("brand.500", "white");
  let textColor = useColorModeValue("secondaryGray.500", "white");
  let brandColor = useColorModeValue("brand.500", "brand.400");
  // 从props中解构出onClick
  const { routes, onClick } = props;
  const activeRoute = (routeName) => {
    return location.pathname.includes(routeName);
  };
  const createLinks = (routes) => {
    return routes.map((route, index) => {
      if (route.category) {
        return (
          <>
            <Text
              fontSize={"md"}
              color={activeColor}
              fontWeight='bold'
              mx='auto'
              ps={{
                sm: "10px",
                xl: "16px",
              }}
              pt='18px'
              pb='12px'
              key={index}>
              {route.name}
            </Text>
            {createLinks(route.items)}
          </>
        );
      } else if (
        route.layout === "/admin" ||
        route.layout === "/auth" ||
        route.layout === "/rtl"
      ) {
        return (
          // 在NavLink上绑定onClick事件,触发传入的onClose方法
          <NavLink key={index} to={route.layout + route.path} onClick={onClick}>
            {route.icon ? (
              <Box>
                <HStack
                  spacing={
                    activeRoute(route.path.toLowerCase()) ? "22px" : "26px"
                  }
                  py='5px'
                  ps='10px'>
                  <Flex w='100%' alignItems='center' justifyContent='center'>
                    <Box
                      color={
                        activeRoute(route.path.toLowerCase())
                          ? activeIcon
                          : textColor
                      }
                      me='18px'>
                      {route.icon}
                    </Box>
                    <Text
                      me='auto'
                      color={
                        activeRoute(route.path.toLowerCase())
                          ? activeColor
                          : textColor
                      }
                      fontWeight={
                        activeRoute(route.path.toLowerCase())
                          ? "bold"
                          : "normal"
                      }>
                      {route.name}
                    </Text>
                  </Flex>
                  <Box
                    h='36px'
                    w='4px'
                    bg={
                      activeRoute(route.path.toLowerCase())
                        ? brandColor
                        : "transparent"
                    }
                    borderRadius='5px'
                  />
                </HStack>
              </Box>
            ) : (
              <Box>
                <HStack
                  spacing={
                    activeRoute(route.path.toLowerCase()) ? "22px" : "26px"
                  }
                  py='5px'
                  ps='10px'>
                  <Text
                    me='auto'
                    color={
                      activeRoute(route.path.toLowerCase())
                        ? activeColor
                        : inactiveColor
                    }
                    fontWeight={
                      activeRoute(route.path.toLowerCase()) ? "bold" : "normal"
                    }>
                    {route.name}
                  </Text>
                  <Box h='36px' w='4px' bg='brand.400' borderRadius='5px' />
                </HStack>
              </Box>
            )}
          </NavLink>
        );
      }
    });
  };
  return createLinks(routes);
}
export default SidebarLinks;

主要修改点:

  1. 从props中解构出onClick参数:const { routes, onClick } = props;
  2. 在每个NavLink元素上添加onClick={onClick},点击导航链接时会同时触发页面跳转和Drawer关闭操作。

内容的提问来源于stack exchange,提问作者Ken Arya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 17:34:55