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

React结合Lenis平滑滚动时页面切换无法回到顶部的问题

问题解决:Lenis平滑滚动下页面跳转时回到顶部失效的修复

问题根源

Lenis会接管原生滚动行为,直接调用window.scrollTo(0,0)无法被Lenis的滚动控制系统识别,尤其是在平滑滚动过程中跳转页面时,Lenis的滚动状态未重置,导致回到顶部功能失效。

解决方案

利用Lenis官方提供的scrollToAPI来控制滚动,替代原生方法,同时在路径变化时重置Lenis的滚动状态。

方案1:通过全局变量传递Lenis实例(快速实现)

1. 修改App.js初始化Lenis

import Lenis from '@studio-freight/lenis';
import { useEffect } from 'react';
import ScrollToTop from './ScrollToTop';
import { BrowserRouter } from 'react-router-dom';

function App() {
  useEffect(() => {
    const lenis = new Lenis();
    
    function raf(time) {
      lenis.raf(time);
      requestAnimationFrame(raf);
    }
    
    requestAnimationFrame(raf);
    // 将Lenis实例挂载到window全局
    window.lenis = lenis;
    
    return () => {
      lenis.destroy();
      delete window.lenis;
    };
  }, []);

  return (
    <BrowserRouter>
      <ScrollToTop />
      {/* 你的路由组件 */}
    </BrowserRouter>
  );
}

export default App;

2. 更新ScrollToTop组件

import { useEffect } from "react";
import { useLocation } from "react-router-dom";
import { colors } from "./constants";

export default function ScrollToTop() {
  const { pathname } = useLocation();

  useEffect(() => {
    if (window.lenis) {
      // 暂停当前平滑滚动,避免冲突
      window.lenis.stop();
      // 立即跳转到顶部,跳过平滑动画
      window.lenis.scrollTo(0, { immediate: true });
      // 重新启动Lenis滚动监听
      window.lenis.start();
    } else {
      // 降级处理:无Lenis时使用原生方法
      window.scrollTo(0, 0);
    }

    document.body.style.backgroundColor = colors.white;
  }, [pathname]);

  return null;
}

方案2:使用React Context传递Lenis实例(最佳实践)

1. 创建LenisContext.js

import { createContext, useContext, useEffect, useRef } from 'react';
import Lenis from '@studio-freight/lenis';

const LenisContext = createContext(null);

export function LenisProvider({ children }) {
  const lenisRef = useRef(null);

  useEffect(() => {
    const lenis = new Lenis();
    
    function raf(time) {
      lenis.raf(time);
      requestAnimationFrame(raf);
    }
    
    requestAnimationFrame(raf);
    lenisRef.current = lenis;
    
    return () => {
      lenis.destroy();
      lenisRef.current = null;
    };
  }, []);

  return (
    <LenisContext.Provider value={lenisRef.current}>
      {children}
    </LenisContext.Provider>
  );
}

export function useLenis() {
  return useContext(LenisContext);
}

2. 修改App.js使用LenisProvider

import { LenisProvider } from './LenisContext';
import { BrowserRouter } from 'react-router-dom';
import ScrollToTop from './ScrollToTop';

function App() {
  return (
    <LenisProvider>
      <BrowserRouter>
        <ScrollToTop />
        {/* 你的路由组件 */}
      </BrowserRouter>
    </LenisProvider>
  );
}

export default App;

3. 更新ScrollToTop组件

import { useEffect } from "react";
import { useLocation } from "react-router-dom";
import { useLenis } from "./LenisContext";
import { colors } from "./constants";

export default function ScrollToTop() {
  const { pathname } = useLocation();
  const lenis = useLenis();

  useEffect(() => {
    if (lenis) {
      lenis.stop();
      lenis.scrollTo(0, { immediate: true });
      lenis.start();
    } else {
      window.scrollTo(0, 0);
    }

    document.body.style.backgroundColor = colors.white;
  }, [pathname, lenis]);

  return null;
}

关键说明

  • immediate: true参数确保页面跳转时直接回到顶部,跳过平滑动画,符合页面切换的用户预期。
  • 每次路径变化时先暂停Lenis滚动,避免新旧页面的滚动状态冲突,完成跳转后再重启监听。
  • 组件卸载时务必销毁Lenis实例,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 03:26:14