Rub*_*uby 6 reactjs react-router next.js
如何像在React-Router-4中那样将Next.js中的活动Link作为目标?意思是,当活动链接的路由处于活动状态时,给活动链接一个类?
Rot*_*eti 85
基于useRouter钩子的简单解决方案:
import Link from "next/link";
import { useRouter } from "next/router";
export const MyNav = () => {
const router = useRouter();
return (
<ul>
<li className={router.pathname == "/" ? "active" : ""}>
<Link href="/">home</Link>
</li>
<li className={router.pathname == "/about" ? "active" : ""}>
<Link href="/about">about</Link>
</li>
</ul>
);
};
Run Code Online (Sandbox Code Playgroud)
小智 17
usePathname() 如果您使用的是 Next 13,您现在可以使用hook执行以下操作:
import { usePathname} from 'next/navigation';
export default function Example() {
const pathname = usePathname();
return(
<div>
<a
href="/welcome"
className={pathname == "/welcome" ?
"active" :
""
}
>
</div>
)
}
Run Code Online (Sandbox Code Playgroud)
小智 12
如果您想使用锚链接,请尝试此版本的 @Rotareti 代码:
import Link from "next/link";
import { useRouter } from "next/router";
export const MyNav = () => {
const router = useRouter();
return (
<ul>
<li className={router.asPath == "/#about" ? "active" : ""}>
<Link href="#about">about</Link>
</li>
</ul>
);
};
Run Code Online (Sandbox Code Playgroud)
另一个支持asprop的最低版本:
import Link from "next/link";
import {withRouter} from "next/router";
import {Children} from "react";
import React from "react";
export default withRouter(({router, children, as, href, ...rest}) => (
<Link {...rest} href={href} as={as}>
{React.cloneElement(Children.only(children), {
className: (router.asPath === href || router.asPath === as) ? `active` : null
})}
</Link>
));
Run Code Online (Sandbox Code Playgroud)
首先,您需要有一个名为Link的组件,其临时属性为activeClassName
import { withRouter } from 'next/router'
import Link from 'next/link'
import React, { Children } from 'react'
const ActiveLink = ({ router, children, ...props }) => {
const child = Children.only(children)
let className = child.props.className || null
if (router.pathname === props.href && props.activeClassName) {
className = `${className !== null ? className : ''} ${props.activeClassName}`.trim()
}
delete props.activeClassName
return <Link {...props}>{React.cloneElement(child, { className })}</Link>
}
export default withRouter(ActiveLink)
Run Code Online (Sandbox Code Playgroud)
然后,使用带有创建的组件链接和CSS选择器的导航栏:active来区分活动链接和非活动链接。
import Link from './Link'
export default () => (
<nav>
<style jsx>{`
.active:after {
content: ' (current page)';
}
.nav-link {
text-decoration: none;
padding: 10px;
display: block;
}
`}</style>
<ul>
<li>
<Link activeClassName='active' href='/'>
<a className='nav-link home-link'>Home</a>
</Link>
</li>
<li>
<Link activeClassName='active' href='/about'>
<a className='nav-link'>About</a>
</Link>
</li>
</ul>
</nav>
)
Run Code Online (Sandbox Code Playgroud)
之后,您可以在页面上实现导航栏:
import Nav from '../components/Nav'
export default () => (
<div>
<Nav />
<p>Hello, I'm the home page</p>
</div>
)
Run Code Online (Sandbox Code Playgroud)
此项工作原理的关键位于组件Link内部,我们将Link中的router.pathnamewith属性值与之进行比较href,如果该值与另一个属性匹配,则放置特定的className以使该链接看起来已激活。
参考:这里
打字稿版本:
import React from 'react'
import Link, { LinkProps } from 'next/link'
import { useRouter } from 'next/router'
export interface NavLinkProps extends LinkProps {
children: React.ReactElement
}
export function NavLink({ children, href, ...props }: NavLinkProps) {
const router = useRouter()
return (
<Link href={href} {...props}>
{router.pathname === href ? React.cloneElement(children, { 'data-active': true }) : children}
</Link>
)
}
Run Code Online (Sandbox Code Playgroud)
请注意,除非必要,否则我不会克隆孩子。
这是 ActiveLink 与NextJS的另一个版本(参见下面的结果图)
import { withRouter } from 'next/router';
import PropTypes from 'prop-types';
import React from 'react';
const ActiveLink = ({ router, href, isLeftSideBar = false, children }) => {
const isCurrentPath = router.pathname === href || router.asPath === href;
const handleClick = (e) => {
e.preventDefault();
router.push(href);
};
(function prefetchPages() {
if (typeof window !== 'undefined') router.prefetch(router.pathname);
})();
const theme =
settings.theme === THEMES.LIGHT && isLeftSideBar ? '#e65100' : '#ffeb3b';
const color = isCurrentPath ? theme : '';
return (
<a
href={href}
onClick={handleClick}
style={{
textDecoration: 'none',
margin: 16,
padding: 0,
fontWeight: isCurrentPath ? 'bold' : 'normal', // I left mine all bold
fontSize: 17,
color: isLeftSideBar ? '#e65100' : '#ffeb3b',
}}>
{children}
</a>
);
};
ActiveLink.propTypes = {
href: PropTypes.string.isRequired,
children: PropTypes.any,
};
export default withRouter(ActiveLink);
Run Code Online (Sandbox Code Playgroud)
随处调用
<ActiveLink href='/signup'> Sign Up </ActiveLink>
Run Code Online (Sandbox Code Playgroud)
结果:
| 归档时间: |
|
| 查看次数: |
5719 次 |
| 最近记录: |