Material-UI と React Router を使う SPA で、必ずと言って良いほど書いているので、いい加減メモしておく。
import React from 'react'; import { NavLink as RouterLink, NavLinkProps as RouterLinkProps, useLocation, } from 'react-router-dom'; import { Omit } from '@material-ui/types'; import { ListItem, ListItemIcon, ListItemText, } from '@material-ui/core'; export interface ListItemLinkProps { icon?: React.ReactElement; primary: string; to: string; } export function ListItemLink(props: ListItemLinkProps) { const { icon, primary, to } = props; const location = useLocation(); const selected = location.pathname.startsWith(to); const renderLink = React.useMemo( () => React.forwardRef<HTMLAnchorElement, Omit<RouterLinkProps, 'innerRef' | 'to'>>( (itemProps, ref) => ( <RouterLink to={to} {...itemProps} innerRef={ref} /> ), ), [to], ); return ( <li> <ListItem button selected={selected} component={renderLink} > {icon ? <ListItemIcon>{icon}</ListItemIcon> : null} <ListItemText primary={primary} /> </ListItem> </li> ); }