我希望活动链接保持悬停样式.当前的样式是使用Chakra UI完成的.

enter image description here

SideNave.jsx

import React, { useState, useEffect } from "react";
import axios from "axios";
import {
  Box,
  CloseButton,
  Flex,
  Hide,
  Image,
  Icon,
  useColorModeValue,
  Drawer,
  DrawerContent,
  useDisclosure
} from "@chakra-ui/react";
import { FiCompass, FiSettings } from "react-icons/fi";
import { NavLink, useLocation } from "react-router-dom";
import {
  AiFillClockCircle,
  AiOutlineTransaction,
  AiOutlineDashboard
} from "react-icons/ai";
import { IoApps, IoLockOpen, IoAnalytics } from "react-icons/io5";
import {
  BsFillPeopleFill,
  BsFillPersonFill,
  BsBookHalf,
  BsCurrencyBitcoin
} from "react-icons/bs";

const LinkItems = [
  {
    name: "Overview",
    icon: AiOutlineDashboard
  },
  { name: "Apps", icon: IoApps },
  { name: "Customers", icon: BsFillPeopleFill },
  { name: "Financial data", icon: IoAnalytics, hasDropdown: true },
  { name: "More", icon: FiSettings, hasDropdown: true }
];

function SideNav() {
  const token = sessionStorage.getItem("token");

  const { isOpen, onOpen, onClose } = useDisclosure();

  return (
    <Box bg={useColorModeValue("gray.100", "gray.900")}>
      <SidebarContent
        onClose={() => onClose}
        display={{ base: "none", md: "block" }}
      />
      <Drawer
        isOpen={isOpen}
        placement="left"
        onClose={onClose}
        returnFocusOnClose={false}
        onOverlayClick={onClose}
        size="full"
      >
        <DrawerContent>
          <SidebarContent onClose={onClose} />
        </DrawerContent>
      </Drawer>
      {/* mobilenav <MobileNav display={{ base: "flex", md: "none" }} onOpen={onOpen} /> */}

      <Box ml={{ base: 0, md: 60 }} p={{ base: 0, md: "4" }}>
        {/* Content */}
      </Box>
    </Box>
  );
}

function SidebarContent({ onClose, post, ...rest }) {
  return (
    <Box
      bg="whiteAlpha.800"
      borderRight="1px"
      borderRightColor={useColorModeValue("gray.200", "gray.700")}
      w={{ base: "full", md: 48, lg: 44, xl: 48, "2xl": 60 }}
      pos="fixed"
      overflow="auto"
      sx={{
        "&::-webkit-scrollbar": {
          width: "6px",
          backgroundColor: "#f1f1f1",
          borderRadius: "68px"
        },
        "&::-webkit-scrollbar-thumb": {
          backgroundColor: "#c1c1c1",
          borderRadius: "68px"
        }
      }}
      h="full"
      {...rest}
    >
      <Flex
        h="20"
        mb={12}
        alignItems="center"
        mx="8"
        justifyContent="space-between"
      >
        <CloseButton display={{ base: "flex", md: "none" }} onClick={onClose} />
      </Flex>
      {LinkItems.map((link) => (
        <React.Fragment key={link.name}>
          {link.name === "Financial data" || link.name === "More" ? (
            <NavItem icon={link.icon} hasDropdown={link.hasDropdown}>
              {link.name}
            </NavItem>
          ) : (
            <div className="nav">
              <NavLink
                to={`/dashboard/${link.name.toLowerCase().replace(" ", "-")}`}
              >
                <NavItem icon={link.icon} hasDropdown={link.hasDropdown}>
                  {link.name}
                </NavItem>
              </NavLink>
            </div>
          )}
        </React.Fragment>
      ))}
    </Box>
  );
}

function NavItem({ icon, children, hasDropdown, ...rest }) {
  const [isDropdownOpen, setIsDropdownOpen] = useState(false);

  const handleDropdownToggle = () => {
    setIsDropdownOpen(!isDropdownOpen);
  };

  return (
    <Box
      as="div"
      style={{ textDecoration: "none" }}
      _focus={{ boxShadow: "none" }}
      mt={4}
    >
      <Flex
        align="center"
        p="2"
        mx="2"
        borderRadius="lg"
        role="group"
        fontSize="15px"
        cursor="pointer"
        _hover={{
          bg: "#002c8a",
          color: "white",
          borderColor: "white"
        }}
        onClick={hasDropdown ? handleDropdownToggle : undefined}
        {...rest}
      >
        {icon && (
          <Icon
            mr="4"
            p={1}
            border="1px"
            borderRadius="full"
            borderColor="gray.400"
            fontSize="24"
            as={icon}
          />
        )}
        {children}
      </Flex>
      {hasDropdown && isDropdownOpen && <DropdownOptions name={children} />}
    </Box>
  );
}

function DropdownOptions({ name }) {
  const options = getDropdownOptions(name);

  const location = useLocation();

  return (
    <Flex
      flexDirection="column"
      ml="4"
      boxShadow="lg"
      w="150px"
      p={2}
      borderRadius="lg"
    >
      {options.map((option) => (
        <NavLink
          key={option.text}
          to={`/dashboard/${option.text.toLowerCase()}`}
        >
          <Box
            key={option}
            className={`dropdown-option ${
              location.pathname.includes(option.text.toLowerCase())
                ? "active-dot"
                : ""
            }`}
            as="div"
            py="2"
            px="1"
            borderRadius="lg"
            w="130px"
            fontSize="14px"
            _hover={{
              bg: "#002c8a",
              color: "white"
            }}
          >
            {option.icon && (
              <Icon
                mr="2"
                fontSize="14"
                verticalAlign="middle"
                as={option.icon}
              />
            )}
            {option.text}
          </Box>
        </NavLink>
      ))}
    </Flex>
  );
}

function getDropdownOptions(name) {
  if (name === "Financial data") {
    return [
      {
        text: "Records",
        icon: AiFillClockCircle
      },
      {
        text: "Transactions",
        icon: AiOutlineTransaction
      },
      { text: "Balance", icon: BsBookHalf },
      {
        text: "Auth",
        icon: IoLockOpen
      }
    ];
  } else if (name === "More") {
    return [
      { text: "Logs", icon: IoAnalytics },
      { text: "Billings", icon: BsCurrencyBitcoin },
      { text: "Teams", icon: FiCompass },
      { text: "Profile", icon: BsFillPersonFill }
    ];
  }

  return [];
}

export default SideNav;

我在这里创造了一个最小的娱乐:https://codesandbox.io/s/navlink-project-n4d6cs?file=/SideNav.jsx

推荐答案

使用NavLink组件的children函数将链接的isActive状态传递到导航项目组件,然后有条件地应用"悬停"样式.

<NavLink
  to={`/dashboard/${link.name.toLowerCase().replace(" ", "-")}`}
>
  {({ isActive }) => ( // <-- isActive prop
    <导航项目
      icon={link.icon}
      hasDropdown={link.hasDropdown}
      isActive={isActive} // <-- pass through
    >
      {link.name}
    </导航项目>
  )}
</NavLink>

导航项目

function 导航项目({ icon, children, hasDropdown, isActive, ...rest }) { // <-- consume
  const [isDropdownOpen, setIsDropdownOpen] = useState(false);

  const handleDropdownToggle = () => {
    setIsDropdownOpen(!isDropdownOpen);
  };

  return (
    <Box
      as="div"
      style={{ textDecoration: "none" }}
      _focus={{ boxShadow: "none" }}
      mt={4}
    >
      <Flex
        align="center"
        p="2"
        mx="2"
        borderRadius="lg"
        role="group"
        fontSize="15px"
        cursor="pointer"
        _hover={{
          bg: "#002c8a",
          color: "white",
          borderColor: "white"
        }}
        onClick={hasDropdown ? handleDropdownToggle : undefined}
        {...(isActive // <-- conditional application
          ? {
              bg: "#002c8a",
              color: "white",
              borderColor: "white"
            }
          : {})}
        {...rest}
      >
        {icon && (
          <Icon
            mr="4"
            p={1}
            border="1px"
            borderRadius="full"
            borderColor="gray.400"
            fontSize="24"
            as={icon}
          />
        )}
        {children}
      </Flex>
      {hasDropdown && isDropdownOpen && <DropdownOptions name={children} />}
    </Box>
  );
}

Edit how-to-style-active-link-in-react-router-dom-v6

Javascript相关问答推荐

在JS中获取名字和姓氏的首字母

为什么JavaScript双边字符串文字插值不是二次的?

获取表格的左滚动位置

Klaro与Angular的集成

如何最好地从TypScript中的enum获取值

如何将连续的十六进制字符串拆分为以空间分隔的十六进制块,每个十六进制块包含32个二元组?

通过嵌套模型对象进行Mongoose搜索

togglePopover()不打开但不关闭原生HTML popover'

使用useEffect,axios和useParams进行react测试

我怎么才能得到Kotlin的密文?

如何在每次单击按钮时重新加载HighChart/设置HighChart动画?

如何将多维数组插入到另一个多维数组中?

如何发送从REST Api收到的PNG数据响应

如何 for each 输入动态设置输入变更值

SPAN不会在点击时关闭模式,尽管它们可以发送日志(log)等

每次重新呈现时调用useState initialValue函数

FireBase云函数-函数外部的ENV变量

rxjs在每次迭代后更新数组的可观察值

在Press Reaction本机和EXPO av上播放单个文件

使用Library chart.js在一个带有两个y轴的图表中绘制两个数据集