Next.js中jQuery代码运行异常 子div轮播添加active类失效
Next.js 无限轮播active类切换异常修复方案
核心问题原因
- 原有jQuery逻辑直接操作DOM,和Next.js的SSR hydration、React虚拟DOM机制冲突:代码执行时DOM可能未完成挂载,后续React重渲染也会覆盖jQuery对DOM的改动
- 定时器未在组件卸载时清除,导致多定时器重复执行,轮播逻辑混乱
- 初始状态未给第一个子元素添加
active类,首次执行时选择器找不到目标元素,逻辑报错 - 部分img标签缺失
data-info属性,读取描述时返回undefined
可选修复方案
方案1:兼容原有jQuery逻辑(临时修复用,不推荐长期使用)
把DOM操作逻辑放到useEffect钩子中执行,确保DOM挂载完成后再初始化轮播,同时添加初始类名、卸载时清除定时器,代码示例:
import { useEffect, useState } from 'react'; import $ from 'jquery'; // 引入对应CSS Module为st,引入ae、pr、ps、xd图片资源 export default function SoftwareCarousel() { const [value, setValue] = useState({ name: 'After effects', description: 'this is aftereffects' }) useEffect(() => { const $container = $(".softwares_container"); // 初始化给第一个子元素加active类 $container.children().eq(0).addClass(st.active); const timerList = []; $container.each(function () { const $currentSet = $(this); const timer = setInterval(function () { const $cur = $currentSet.find(`.${st.active}`).removeClass(`${st.active}`); const $next = $cur.next().length ? $cur.next() : $currentSet.children().eq(0); $next.addClass(`${st.active}`); const $nextInner = $next.children().eq(0); setValue({ name: $nextInner.attr('alt'), description: $nextInner.attr('data-info') || '' }) }, 1000); timerList.push(timer) }) // 组件卸载时清除所有定时器,避免内存泄漏和逻辑冲突 return () => { timerList.forEach(timer => clearInterval(timer)) } }, []) return ( <div> <div className={`softwares_container ${st.left_container}`}> <div className={` ${st.img}`} alt="1"> <img src={ae.src} data-info="this is aftereffects" alt="After effects" /> </div> <div className={st.img} alt="2"> <img src={pr.src} alt="Adobe Premiere pro" data-info="this is adobe premiere pro" /> </div> <div className={st.img}> <img src={ps.src} alt="Adobe Photoshop" data-info="this is adobe photoshop" /> </div> <div className={st.img}> <img src={xd.src} alt="Adobe Xd" data-info="this is adobe xd" /> </div> </div> {/* 信息展示区域 */} <div className={st.content}> <h3>{value.name}</h3> <p>{value.description}</p> </div> </div> ) }
方案2:React状态驱动实现(推荐,符合Next.js开发规范)
完全移除jQuery依赖,用组件状态控制轮播逻辑和类名切换,从根源避免虚拟DOM和原生DOM操作的冲突,代码更易维护:
import { useEffect, useState } from 'react'; // 引入对应CSS Module为st,引入ae、pr、ps、xd图片资源 // 统一维护轮播数据 const softwareItems = [ { name: 'After effects', description: 'this is aftereffects', imgSrc: ae.src }, { name: 'Adobe Premiere pro', description: 'this is adobe premiere pro', imgSrc: pr.src }, { name: 'Adobe Photoshop', description: 'this is adobe photoshop', imgSrc: ps.src }, { name: 'Adobe Xd', description: 'this is adobe xd', imgSrc: xd.src } ] export default function SoftwareCarousel() { const [activeIndex, setActiveIndex] = useState(0); useEffect(() => { const timer = setInterval(() => { // 循环更新索引,到最后一项时回到第一个 setActiveIndex(prev => prev === softwareItems.length - 1 ? 0 : prev + 1) }, 1000) // 组件卸载清除定时器 return () => clearInterval(timer) }, []) const currentActive = softwareItems[activeIndex] return ( <div> <div className={`softwares_container ${st.left_container}`}> {softwareItems.map((item, index) => ( <div key={item.name} // 索引匹配时添加active类 className={`${st.img} ${index === activeIndex ? st.active : ''}`} alt={index + 1} > <img src={item.imgSrc} data-info={item.description} alt={item.name} /> </div> ))} </div> {/* 信息展示区域 */} <div className={st.content}> <h3>{currentActive.name}</h3> <p>{currentActive.description}</p> </div> </div> ) }
方案说明
- 方案1仅对原有jQuery代码做生命周期适配,后续如果组件出现重渲染,依然可能出现DOM被覆盖、类名丢失的问题,只适合临时快速修复
- 方案2完全遵循React数据驱动视图的设计理念,没有原生DOM操作,不存在和虚拟DOM的冲突问题,逻辑清晰易维护,是Next.js项目下的首选实现
内容的提问来源于stack exchange,提问作者Diptanu Chakraborty
相关产品推荐
相关产品推荐

