封装一个 NavLink 组件并使用 Styled Component 对其进行样式化

Encapsulate a NavLink component and style it with Styled Component

我正在尝试创建一个带有来自 react-rounter-dom 库组件 NavLink 的超链接的菜单 并使用 styled component

设置样式

我创建了一个名为 Link 的组件,它位于 NavLink 所在的位置,因此您无需多次重复同一行代码,然后将此组件传递给样式化组件以继承其属性您可以对其应用样式。

但是样式没有应用到我的组件

NavLink

import { NavLink as NavLinkReactRouterDom } from "react-router-dom";

const Link = function ({ to, children, ...props }) {
  return (
    <>
      <NavLinkReactRouterDom
        {...props}
        className={({ isActive }) =>
          // console.log(isActive)
          isActive ? "is-active" : undefined
        }
        to={to}
      >
        {children}
      </NavLinkReactRouterDom>
    </>
  );
};
export default Link;

sidebarStyled.js (css)

import styled from "styled-components";
import Link from "./NavLink";
//    NavLink
export const Prueba = styled(Link)`
  color: white;
  font-size: 50px;
  text-decoration: none;
  display: flex;
  justify-content: flex-start;
  align-items: stretch;
  flex-direction: row;

  &.is-active {
    color: green;
  }
`

边栏

const Sidebar = function () {
  return (
    <SidebarContainer>
      <LogoContainer>
        <img src={Logo} alt="Logo" />
      </LogoContainer>
      <h1>Sidebe Here</h1>
      <Divider />
      <Menu>
        <NavList>
          <NavItem>
            <Prueba to="/">
              <LinkIcon icon="typcn:home-outline" />
              Inicio
            </Prueba>
          </NavItem>
        </NavList>
      </Menu>
    </SidebarContainer>
  );
};
export default Sidebar;

您可能需要使用 Prueba,而不是 Link。由于您继承了 Link 组件,因此应用了自定义 CSS 并将其存储在名为 Prueba 的变量中。

因此将其导入 sidebar.js 文件并在那里使用

参考:https://codesandbox.io/s/objective-smoke-1bflsh?file=/src/App.js

添加

import 'Prueba' from sidebarStyled.js'

改变

....
<Prueba to="/">
   <LinkIcon icon="typcn:home-outline" />
    Inicio
</Prueba>
....

问题

已设置样式的组件的 className 属性 Prueba 不会传递给它试图设置样式的组件,即 NavLinkReactRouterDom 组件。或者更确切地说,它 当道具散布到其中时隐式传递,但是 NavLinkReactRouterDom 是覆盖并设置它自己的 className 道具。

const Link = function ({ to, children, ...props }) {
  return (
    <>
      <NavLinkReactRouterDom
        {...props} // <-- styled-component className pass here
        className={({ isActive }) => // <-- overridden here!
          // console.log(isActive)
          isActive ? "is-active" : undefined
        }
        to={to}
      >
        {children}
      </NavLinkReactRouterDom>
    </>
  );
};

解决方案

解决方案是将 styled-component 的 className 属性与用于 NavLinkReactRouterDom 组件的活动类名合并。

示例:

const Link = function ({ to, children, className, ...props }) {
  return (
    <NavLinkReactRouterDom
      {...props}
      className={({ isActive }) =>
        [className, isActive ? "is-active" : null].filter(Boolean).join(" ")
      }
      to={to}
    >
      {children}
    </NavLinkReactRouterDom>
  );
};