Himanshu Sharma
Himanshu Sharma

Reputation: 345

Changing style of Component inside NavLink

I am making a navbar, using NavLink from React-Router-Dom. Using 'isActive' prop to style the active Link, is okay. But, how could I style the subelements inside of it. To be exact, please see this ...

const Nav = [
{path : '/', icon : <NavIcon.Home />},
{path : '/service', icon : <NavIcon.Service />}
]

function someFunc(){
return (
Nav.map(({path, icon}) => (
<NavLink key={path} to ={path}>
{icon} //this icon is actually an svg icon and i want to change its 'fill' attr. conditionally, when the navLink is active or not. I am using .ts
</NavLink>
))}
}

const Home = () => {
<svg ....other attributes ....  fill ={isActive ? 'color1' : 'color2'}> //I want this fill to be conditional so based on as to link is active or not. (**this svg exists into different component, as so do the NavLink**).
...
</svg>
}

how should I use 'isActive' from navLink inside of my svg component? and connect to 'isActive' inside of inside of entirely different component?

ps : - I TRIED making interface type in svg component as

interface Props extends NavLinkProps {
isActive : boolean;
}

const Home = ({isActive} : Props) => {
return (
<svg fill ={isActive ? 'color1' : 'color2'}>
...
</svg>
)
}

and then tried using this into my Nav.tsx component

const Nav = [
{path : '/', icon : <NavIcon.Home isActive = {'what should I put here?'} />},
    {path : '/service', icon : <NavIcon.Service isActive = {} />}
]

return (
<NavLink to ={path} key ={path} className = {({isActive}) => isActive ? 'class1' : 'class2'}>
{icon}
</NavLink>
)

"My main aim is to change the 'fill color' of the svg wrapped around NavLink , based on whether the NavLink is active or not"

Upvotes: 0

Views: 902

Answers (1)

Drew Reese
Drew Reese

Reputation: 202608

In addition to the NavLink component taking a function prop on the className and style props, the children prop can also take a function and is passed the isActive property.

NavLink

declare function NavLink(
  props: NavLinkProps
): React.ReactElement;

interface NavLinkProps
  extends Omit<
    LinkProps,
    "className" | "style" | "children"
  > {
  caseSensitive?: boolean;
  children?:
    | React.ReactNode
    | ((props: { isActive: boolean }) => React.ReactNode);
  className?:
    | string
    | ((props: {
        isActive: boolean;
      }) => string | undefined);
  end?: boolean;
  style?:
    | React.CSSProperties
    | ((props: {
        isActive: boolean;
      }) => React.CSSProperties);
}

Reconfigure the Nav array to instead hold a reference to the icon component you want to render and pass extraneous props to at runtime.

const nav = [
  { path: '/', end: true, icon: NavIcon.Home }, // only match when exactly "/"
  { path: '/service', icon: NavIcon.Service }
];

When mapping the nav array use the children function prop and pass the isActive property as a prop to the icon component.

nav.map(({ icon: Icon, ...props }) => (
  <NavLink key={props.path} {...props}>
    {({ isActive }) => <Icon isActive={isActive} />}
  </NavLink>
))}

Upvotes: 1

Related Questions