Next.js+react-scroll滚动到底部时如何设置最后一个section为激活状态?
React Scroll滚动到底部时激活链接不更新的问题解决
问题
用Next.js搭配react-scroll做的项目,粘性导航栏的激活链接会跟着视口里的section自动切换,但滚到页面底部时,激活状态停在section4,不会切到最后一个section7。已经开了spy={true}和smooth={true},所有section高度固定,滚动也流畅,就是最后一个section的激活状态触发不了。
复现代码
"use client" import { Link, Element } from "react-scroll" export default function Home() { return ( <div> <div className="flex gap-2 items-center justify-center h-10 w-full bg-white sticky top-0"> {Array.from({ length: 8 }).map((i, index) => ( <Link key={index} to={`section${index}`} spy={true} smooth={true} className="[&.active]:text-amber-500" > to section {index} </Link> ))} </div> {Array.from({ length: 8 }).map((i, index) => ( <Element key={index} name={`section${index}`} className="h-56 w-full bg-amber-100 mb-2" > section {index} </Element> ))} </div> ) }
解决方法
1. 调整react-scroll的激活阈值
react-scroll默认的spy判断逻辑比较严格,最后一个section可能因为没完全占满视口顶部而不触发激活。给<Link>加个threshold参数,降低激活所需的可见比例:
<Link key={index} to={`section${index}`} spy={true} smooth={true} threshold={0.1} // 元素可见10%就激活对应链接 className="[&.active]:text-amber-500" > to section {index} </Link>
也可以试试offset={-10},调整滚动偏移量,让滚动到接近底部时提前触发激活。
2. 自定义滚动监听逻辑
如果上面的方法没用,就自己写滚动监听,手动判断最后一个section的可见状态:
"use client" import { Link, Element } from "react-scroll" import { useEffect, useState } from "react" export default function Home() { const [activeSection, setActiveSection] = useState("section0") useEffect(() => { const handleScroll = () => { const sections = document.querySelectorAll("[data-scroll-id]") const lastSection = sections[sections.length - 1] const lastRect = lastSection.getBoundingClientRect() // 检测是否滚动到页面底部,同时最后一个section可见 const isAtBottom = window.innerHeight + window.scrollY >= document.body.offsetHeight - 10 if (isAtBottom && lastRect.top <= window.innerHeight) { setActiveSection(lastSection.getAttribute("data-scroll-id")!) return } // 处理其他section的激活 sections.forEach(section => { const rect = section.getBoundingClientRect() // 100是导航栏的高度,根据自己的导航栏高度调整 if (rect.top <= 100 && rect.bottom >= 100) { setActiveSection(section.getAttribute("data-scroll-id")!) } }) } window.addEventListener("scroll", handleScroll) return () => window.removeEventListener("scroll", handleScroll) }, []) return ( <div> <div className="flex gap-2 items-center justify-center h-10 w-full bg-white sticky top-0"> {Array.from({ length: 8 }).map((i, index) => ( <Link key={index} to={`section${index}`} spy={false} // 关掉默认spy,用自定义逻辑 smooth={true} className={`${activeSection === `section${index}` ? 'text-amber-500' : ''}`} > to section {index} </Link> ))} </div> {Array.from({ length: 8 }).map((i, index) => ( <Element key={index} name={`section${index}`} data-scroll-id={`section${index}`} className="h-56 w-full bg-amber-100 mb-2" > section {index} </Element> ))} </div> ) }
3. 给最后一个section加额外空间
如果最后一个section高度不够,给它加个底部内边距或者调高高度,让它能被react-scroll的spy检测到:
{Array.from({ length: 8 }).map((i, index) => ( <Element key={index} name={`section${index}`} className={`h-56 w-full bg-amber-100 mb-2 ${index === 7 ? 'pb-16' : ''}`} > section {index} </Element> ))}
内容的提问来源于stack exchange,提问作者Tareq Al Mozayek
相关产品推荐
相关产品推荐

