我正在尝试将
styled-components
与 NavLink
中的 react-router-dom@6
一起使用。
import styled from "styled-components";
import { NavLink as BaseNavLink } from "react-router-dom";
export const StyledNavLink = styled(BaseNavLink)``;
然后使用上面的
StyledNavLink
,如下所示
<Styled.StyledNavLink
className={({ isActive }:any) => (isActive ? "active" : "")}
to="/contact"
>
Contact
</Styled.StyledNavLink>
但是在生成链接时的 UI 中,其类如下所示,
<a aria-current="page" class="sc-hLseeU befAUD ({
isActive
}) => isActive ? "active" : "" active" href="#/contact">
Contact
</a>
请检查
<a>
标签的类属性。除了活动类之外,它还具有所有函数定义。
以前在
react-router-dom@5
中从未发生过这种情况,但在迁移到 react-router-dom@6
后却出现了。
styled-component
styled
实用程序会覆盖 className
属性。它将任何传递的 className
函数字符串化并将其注入到 DOM 中。为了解决这个问题,您需要实现一些自定义逻辑,以将 NavLink
className
逻辑应用到另一个不会被覆盖的道具上,然后将其与 className
注入的常规字符串 styled
道具合并.
NavLink.styled.ts
已重命名为 NavLink.styled.tsx
,因此 TSX 在文件中有效使用。
import styled from "styled-components";
import { NavLink as BaseNavLink } from "react-router-dom";
import type { NavLinkProps as BaseNavLinkProps } from "react-router-dom";
interface NavLinkProps extends BaseNavLinkProps {
customClassName?:
| string
| ((props: {
isActive: boolean;
isPending?: boolean;
}) => string | undefined);
}
const NavLink = ({ customClassName, className, ...props }: NavLinkProps) => {
const getCustomClassName = (props) => {
switch (typeof customClassName) {
case "function":
return customClassName(props);
case "string":
return customClassName;
default:
return undefined;
}
};
return (
<BaseNavLink
className={(props) =>
[
getCustomClassName(props), // NavLink "prop"
className // styled-component "prop"
]
.filter(Boolean)
.join(" ")
}
{...props}
/>
);
};
export const StyledNavLink = styled(NavLink)<NavLinkProps>``;
使用
StyledNavLink
组件的 UI 将使用 customClassName
属性而不是 className
并传递相同的函数或字符串值。
function App() {
return (
<HashRouter>
<nav>
<StyledNavLink
to="/home"
customClassName={({ isActive }) => (isActive ? "current" : "")}
>
Home
</StyledNavLink>
<StyledNavLink
to="/about"
customClassName={({ isActive }) => (isActive ? "current" : "")}
>
About Us
</StyledNavLink>
<StyledNavLink
customClassName="current" // <-- always applied
to="/contact"
>
Contact
</StyledNavLink>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/home" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<ContactUs />} />
</Routes>
</HashRouter>
);
}
样式化 NavLink 将函数定义添加到类属性的主要原因是样式化组件的工作方式。 styled-components 使用一种名为“标记模板文字”的技术来为组件创建 CSS 样式,这意味着 CSS 样式实际上是 JavaScript 代码,而函数定义是该代码的一部分。 在 React Router Dom v6 中,NavLink 组件现在使用名为 activeClassName 的 prop 来指定在 NavLink 处于活动状态时应用到的类。这意味着类属性中不再需要函数定义,因为 activeClassName 属性会处理它。
这是我更改的代码
import styled from "styled-components";
import { NavLink as BaseNavLink } from "react-router-dom";
export const StyledNavLink = styled(BaseNavLink)`
`;
const NavLink = ({ to, activeClassName }) => (
<Styled.StyledNavLink
className={activeClassName}
to={to}
>
...
</Styled.StyledNavLink>
);
export default NavLink;
我认为这将从类属性中删除函数定义,并且 NavLink 的样式将正确。