在 Next.js 中应避免直接操作 DOM,推荐使用 useState 管理唯一激活按钮的状态:通过一个数字索引(如 0, 1)标识当前激活项,并在点击时更新该状态,再动态绑定 className 实现视觉反馈。
在 next.js 中应避免直接操作 dom,推荐使用 `usestate` 管理唯一激活按钮的状态:通过一个数字索引(如 `0`, `1`)标识当前激活项,并在点击时更新该状态,再动态绑定 `classname` 实现视觉反馈。
在 React 生态(尤其是 Next.js)中,状态驱动 UI 是核心范式。手动调用 document.querySelectorAll() 移除 class 不仅违背 React 的声明式原则,还可能引发服务端渲染(SSR)不一致、水合错误(hydration mismatch)等严重问题。正确的做法是将“哪个按钮处于激活态”这一事实抽象为组件内部状态。
以下是一个清晰、可扩展、符合最佳实践的实现方案:
import { useState } from 'react';function HebdoSelector() { const [activeIndex, setActiveIndex] = useState<number | null>(null); return ( <div className="flex py-24 bg-hebdo w-full"> <div className="flex flex-col gap-5 justify-center items-center w-full"> <h2>HEBDO</h2> <div className="flex items-center justify-between gap-2 border flex-grow"> <button className={`py-1.5 px-2 rounded-[3px] text-orange-white-light bg-[#ffffff40] ${activeIndex === 0 ? 'active' : ''}`} onClick={() => setActiveIndex(0)} aria-pressed={activeIndex === 0} > <DayItem /> </button> <button className={`py-1.5 px-2 rounded-[3px] text-orange-white-light bg-[#ffffff40] ${activeIndex === 1 ? 'active' : ''}`} onClick={() => setActiveIndex(1)} aria-pressed={activeIndex === 1} > <DayItem /> </button> </div> </div> </div> );}export default HebdoSelector;
若按钮数量较多或需动态生成,可进一步封装为数组映射:
const days = ['Mon', 'Tue']; // 或从 props / context 获取return ( <div className="flex items-center justify-between gap-2 border flex-grow"> {days.map((_, idx) => ( <button key={idx} className={`py-1.5 px-2 rounded-[3px] text-orange-white-light bg-[#ffffff40] ${activeIndex === idx ? 'active' : ''}`} onClick={() => setActiveIndex(idx)} aria-pressed={activeIndex === idx} > <DayItem day={idx} /> </button> ))} </div>);
遵循此模式,你不仅能解决当前问题,更能建立起对 React 状态管理的正确认知,为构建健壮的 Next.js 应用打下坚实基础。