I am trying to use styled-components
with NavLink
from react-router-dom@6
.
import styled from "styled-components";
import { NavLink as BaseNavLink } from "react-router-dom";
export const StyledNavLink = styled(BaseNavLink)``;
and then use above StyledNavLink
like below
<Styled.StyledNavLink
className={({ isActive }:any) => (isActive ? "active" : "")}
to="/contact"
>
Contact
</Styled.StyledNavLink>
But in the UI when the link is generated, its class looks like below,
<a aria-current="page" class="sc-hLseeU befAUD ({
isActive
}) => isActive ? "active" : "" active" href="#/contact">
Contact
</a>
Please check the class attribute of the <a>
tag. It has all the function definition in addition to the active class.
This never used to happen with react-router-dom@5
, but it’s happening after migrating to react-router-dom@6
.
2
Answers
The main reason why the styled NavLink is adding the function definition to the class attribute is because of the way that styled-components works. styled-components uses a technique called tagged template literals to create the CSS styles for a component which means that the CSS styles are actually JavaScript code, and the function definition is part of that code.
In React Router Dom v6, the NavLink component now uses a prop called activeClassName to specify the class that is applied to the NavLink when it is active. This means that the function definition is no longer needed in the class attribute, because the activeClassName prop will take care of it.
Here’s the code which I have changed
I think this will remove the function definition from the class attribute, and the NavLink will be styled correctly.
The
styled-component
styled
utility overrides theclassName
prop. It’s stringifying any passedclassName
function and injecting it into the DOM. To get around this you’ll need to implement some custom logic to apply theNavLink
className
logic on another prop that won’t be overwritten and then merge it along with the regular stringclassName
prop thatstyled
injects.NavLink.styled.ts
is renamed toNavLink.styled.tsx
so TSX is validly used in the file.The UI using the
StyledNavLink
component will use ancustomClassName
prop instead ofclassName
and pass the same function or string value.