You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NextJS中如何通过单选按钮实现页面导航并维持选中状态?

解决NextJS侧边栏导航高亮不持久的问题

当前代码修复方案

你的问题核心是页面跳转后组件重新渲染,单选按钮的选中状态丢失,导致peer-checked样式无法触发。另外React中label的for属性需要改为htmlFor(避免和JS关键字冲突),按以下步骤修改:

  1. 导入Next.js的路由钩子(App Router用usePathname,Pages Router用useRouter)
  2. 根据当前路由设置单选按钮的checked属性
  3. 修正label的for为htmlFor

代码示例(App Router)

import { usePathname } from 'next/navigation';
import Link from 'next/link';
import { useState } from 'react';

export default function Sidebar() {
  const pathname = usePathname();
  const [done, setDone] = useState(pathname === '/' ? 'first' : 'second');

  return (
    <div>
      <Link href="/">
        <input
          name="connected"
          id="home"
          type="radio"
          className="peer/home"
          value="first"
          checked={pathname === '/'}
          onChange={(e) => setDone(e.target.value)}
        />
        <label
          htmlFor="home"
          className="bg-red-500 peer-checked/home:bg-blue-500"
        >
          Click me
        </label>
      </Link>
      <br />
      <Link href="/trucks">
        <input
          name="connected"
          id="no"
          type="radio"
          className="peer/no"
          value="second"
          checked={pathname === '/trucks'}
          onChange={(e) => setDone(e.target.value)}
        />
        <label
          htmlFor="no"
          className="bg-red-500 peer-checked/no:bg-blue-500"
        >
          Click here
        </label>
      </Link>
    </div>
  );
}

代码示例(Pages Router)

import { useRouter } from 'next/router';
import Link from 'next/link';
import { useState } from 'react';

export default function Sidebar() {
  const router = useRouter();
  const [done, setDone] = useState(router.pathname === '/' ? 'first' : 'second');

  return (
    <div>
      <Link href="/">
        <input
          name="connected"
          id="home"
          type="radio"
          className="peer/home"
          value="first"
          checked={router.pathname === '/'}
          onChange={(e) => setDone(e.target.value)}
        />
        <label
          htmlFor="home"
          className="bg-red-500 peer-checked/home:bg-blue-500"
        >
          Click me
        </label>
      </Link>
      <br />
      <Link href="/trucks">
        <input
          name="connected"
          id="no"
          type="radio"
          className="peer/no"
          value="second"
          checked={router.pathname === '/trucks'}
          onChange={(e) => setDone(e.target.value)}
        />
        <label
          htmlFor="no"
          className="bg-red-500 peer-checked/no:bg-blue-500"
        >
          Click here
        </label>
      </Link>
    </div>
  );
}

更高效的实现思路

用单选按钮实现导航高亮属于冗余方案,直接通过当前路由动态给Link添加样式类是更简洁的写法,无需维护表单状态:

代码示例(App Router)

import { usePathname } from 'next/navigation';
import Link from 'next/link';

export default function Sidebar() {
  const pathname = usePathname();

  return (
    <div className="flex flex-col gap-2">
      <Link
        href="/"
        className={`px-4 py-2 rounded transition-colors ${
          pathname === '/' ? 'bg-blue-500 text-white' : 'bg-red-500 text-black'
        }`}
      >
        Click me
      </Link>
      <Link
        href="/trucks"
        className={`px-4 py-2 rounded transition-colors ${
          pathname === '/trucks' ? 'bg-blue-500 text-white' : 'bg-red-500 text-black'
        }`}
      >
        Click here
      </Link>
    </div>
  );
}

优势说明

  • 代码更简洁,去掉了冗余的表单元素和状态管理
  • 直接基于路由判断样式,避免页面跳转后状态丢失的问题
  • 符合NextJS导航组件的常规写法,易于维护和扩展

内容的提问来源于stack exchange,提问作者Zach philipp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 08:20:27