首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

由useEffect重新渲染后,React页面滚动在顶部

当通过 useEffect 函数重新渲染 React 页面时,页面滚动位置将会回到顶部。

useEffect 是 React 提供的一个副作用钩子,用于处理组件中的副作用操作,比如订阅事件、数据获取等。它在每次渲染结束后执行,包括组件的初次渲染和每次更新渲染。

当在 useEffect 中执行一些操作会导致组件重新渲染时,例如修改了依赖项数组(dependencies),React 将重新渲染组件,并且由于重新渲染,页面的滚动位置将重置为顶部。

这种行为对于大多数场景是有益的,因为在组件重新渲染后,用户通常希望页面的滚动位置回到最上方。然而,如果你希望在页面滚动后保持滚动位置不变,可以通过以下方式实现:

  1. 使用 useRef 钩子保存滚动位置:
代码语言:txt
复制
import { useEffect, useRef } from 'react';

function MyComponent() {
  const scrollRef = useRef();

  useEffect(() => {
    if (scrollRef.current) {
      window.scrollTo(0, scrollRef.current);
    }
  }, []);

  useEffect(() => {
    scrollRef.current = window.pageYOffset;
  });

  return (
    // your component JSX
  );
}

在上述代码中,我们使用 useRef 创建了一个 ref,用于保存滚动位置。在组件每次渲染时,都会更新 ref 中的值为当前页面的滚动位置。然后,在 useEffect 中通过 window.scrollTo 方法将滚动位置恢复为之前保存的值。

  1. 使用 scrollTo 方法并结合滚动事件进行处理:
代码语言:txt
复制
import { useEffect, useState } from 'react';

function MyComponent() {
  const [scrollPosition, setScrollPosition] = useState(0);

  useEffect(() => {
    window.scrollTo(0, scrollPosition);
  }, [scrollPosition]);

  useEffect(() => {
    const handleScroll = () => {
      setScrollPosition(window.pageYOffset);
    };

    window.addEventListener('scroll', handleScroll);

    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  }, []);

  return (
    // your component JSX
  );
}

在上述代码中,我们使用 useState 创建了一个状态变量 scrollPosition,用于保存滚动位置。在每次滚动事件触发时,都会更新 scrollPosition 的值。然后,在 useEffect 中监听滚动事件,并通过 window.scrollTo 方法将滚动位置恢复为 scrollPosition 的值。

总结起来,当使用 useEffect 重新渲染 React 页面后,页面滚动位置会回到顶部。如果需要在重新渲染后保持滚动位置不变,可以利用 useRef 或 useState 结合 scrollTo 方法进行处理。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

10分钟教你手写8个常用的自定义hooks

我们使用hooks和函数组件编写我们的组件时,第一个要考虑的就是渲染性能,我们知道如果在不做任何处理时,我们函数组件中使用setState都会导致组件内部重新渲染,一个比较典型的场景: ?...当我们容器组件手动更新了任何state时,容器内部的各个子组件都会重新渲染,为了避免这种情况出现,我们一般都会使用memo将函数组件包裹,来达到class组件的pureComponent的效果: import...状态a的更新将不会导致B组件重新渲染。...组件不会再重新渲染。...,我们钩子函数里需要传入一个元素的引用,这个我们可以函数组件中采用ref和useRef来获取到,钩子返回了滚动的x,y值,即滚动的左位移和顶部位移,具体使用如下: import React, { useRef

2.8K20
  • React项目中如何实现一个简单的锚点目录定位

    前言 锚点目录定位功能在长页面和文档类网站中非常常见,它可以让用户快速定位到页面中的某个章节 如何在React中实现锚点定位和平滑滚动 目录自动高亮的实现思路 处理顶部导航遮挡锚点的解决方案 服务端渲染下的实现方案...SSR支持 Next.js等SSR场景下,客户端脚本会延后加载,页面初次渲染时目录联动会失效。...import { useEffect } from 'react'; function App({ chapters }) { useEffect(() => { ReactDOM.hydrate...但是Next.js的SSR环境下就会有问题: 点击目录链接时,页面不会滚动。 这是因为服务端,我们无法获取组件的ref,所以锚点元素不存在,自然无法定位。 滚动页面时,目录高亮也失效。...简单来说就是: 服务端渲染时,读取路由参数,提前计算高亮状态 将高亮数据注入到响应中 客户端拿到注水的数据渲染,不会出现高亮错位 实现步骤: 1.服务端获取参数和数据 // getServerSideProps

    98820

    前端架构探索与实践

    并且根据 component 的配置来渲染不同的组件到页面中,首屏组件和按需加载组件。最后,支撑到每一个对应的页面里面。 分工组织 ?...对于一个页面,无论是 react 还是 rax,其实都是 fn(x)=>UI 的过程。所以整理流程无非就是拿到接口属于渲染到 UI 中。所以对于中间页的架构而言也是如此。...但是尴尬至于在于,iOS 的橡皮筋想过,页面滚动顶部以后,如果页面有频繁的动画或者 setState 的时候,会导致页面重绘,重新回到顶部。...与手动下拉页面容器的橡皮筋效果冲突,而「倒是页面疯狂抖动」。所以。。。。重构。 旧版容器功能点 ❝源码页面中使用的部分 ❞ ? 重构的使用 ❝基本没有太大改变 ❞ ?...为当前所在文件夹的文件夹名称 升级为拍卖源码架构,下载对应脚手架模板:init-project 已init rax的项目中调用 升级为拍卖源码架构,下载对应脚手架模板:init-project ❝

    98820

    虚拟列表与 Scroll Restoration

    虚拟列表的原理是只渲染可视部分以及部分预渲染的节点,待滚动之后替换可视部分节点。余下的空间则用 padding-top padding-bottom 撑开。...渲染 50 个 Node,实际只渲染了可见部分的 Node 本篇文章不讨论如何实现一个虚拟列表,此类文章网上有很多。但是有关于回退页面无法回到虚拟列表上一次的位置的文章却很少。...,即使开启了 Restoration,回退页面仍然无法回到上一次的位置。...对于 react-virtuoso 这个库,没有直接暴露给我们每个 Node 计算的高度,也没有一个自身的 State 想要缓存状态不太现实。...一个不好的解决方案是用提供的接口每次滚动后记录一个 Range,Range 是一个当前渲染内容的索引,之后的渲染可以用自身的 scrollTo 方法跳转。

    86820

    如何处理 React 中的 onScroll 事件?

    React 应用中,我们经常需要处理滚动事件(onScroll),以实现一些与滚动相关的功能,如无限滚动加载、滚动顶部按钮等。...添加滚动事件监听器 React 中,我们可以通过元素上添加 onScroll 属性来监听滚动事件。通过指定一个回调函数,我们可以滚动事件触发时执行相应的逻辑。...通过使用 useEffect 钩子,我们组件挂载时添加滚动事件的监听器,然后组件卸载时移除监听器。注意在 useEffect 的依赖项数组中传入一个空数组 [],以确保监听器只被添加一次。...虚拟化技术只渲染可见区域内的元素,而不是全部渲染。这样可以减少 DOM 操作和计算量,提高滚动的流畅性和响应速度。...通过合理处理滚动事件,我们可以实现一些常见的滚动相关功能,如无限滚动加载、滚动顶部按钮等。

    3.3K10

    Effect:渲染本身引起的副作用

    React 组件中的两种逻辑类型: 渲染逻辑代码 位于组件的顶层,接收 props 和 state,进行转换,返回屏幕上看到的 JSX,只计算不做其他任何事情; 事件处理程序 嵌套在组件内部的函数,特定的用户操作...⭐Effect 允许指定渲染本身,而不是特定事件引起的副作用。...useEffect(() => {}); 组件挂载执行 useEffect(() => {}, []); 每次 渲染,且 a 或 b 的值与上次渲染不一致时执行 useEffect(() => {...}, [a, b]); ⭐ 响应式值必须包含在依赖项中,组件内部声明的 props、state 和其他值都是 响应式 的,因为它们是渲染过程中计算的,并参与了 React 的数据流。...React 会验证是否将每个响应式值都指定为了依赖项 1 当指定的所有依赖项在上一次渲染期间的值与当前值完全相同时,React 会跳过重新运行该 Effect。

    6600

    亲手打造属于你的 React Hooks

    resetInterval]); return [isCopied, handleCopy]; } 最后,我们可以做的最后一个改进是将 handleCopy包装在useCallback钩子中,以确保它不会在每次有重新渲染时被重新创建... : } ); } usePageBottom Hook React 应用中,有时了解用户何时滚动页面底部是很重要的...在你可以无限滚动的应用中,比如微博,一旦用户点击页面底部,你就需要获取更多的帖子。 让我们看看如何自己创建一个 usePageBottom钩子,用于类似的用例,比如创建无限滚动。...如果这两个值相等,结果将为真,并且用户已经滚动页面底部: // utils/usePageBottom.js import React from "react"; export default function...我们可以通过创建一个本地函数来重新计算这个表达式,该函数在用户滚动时被调用,称为handleScroll。

    10.1K60

    蜕变之始,useEffect 最后一种用法

    React 官方文档中,对于 useEffect 有这样一句描述:Effects are an escape hatch from the React paradigm。 这句话怎么理解呢?...Figma 1 如何运用 useEffect 第二个参数为一个数组,当我们传入的参数为一个空数组时,表示 effect 仅会在组件首次渲染完成时执行。...2 需求 页面滚动的过程中,我们常常会在页面顶部或者旁边,放一个标识组件来告诉用户页面已经滚动到什么位置了。 滚动的过程中,当前选中状态会自动变化到对应的位置。... 页面滚动的过程中,目标元素相对于可视区域的位置会随时发生变化。...因此我们可以 effect 中添加 document 的滚动事件监听 useEffect(() => { document.addEventListener('scroll', () => {

    13610

    手写一个 OnBoarding 组件

    antd5 也加入了这种组件: 那它是怎么实现的呢? 调试下可以发现,遮罩层 4 个 react 元素组成。...首先,把目标元素滚动到可视区域: 这个用 scrollIntoView 方法实现: MDN 上可以看到它的介绍: 设置 block、inline 为 center 是把元素中心滚动到可视区域中心的意思...onStepsEnd 是全部完成的回调。...效果就是 dom 渲染完之后,触发重新渲染,从而渲染这个 OnBoarding 组件: 第一次渲染的时候,元素是 null,触发重新渲染之后,就会渲染下面的 Mask 了: Onboarding/index.tsx...只是现在结束,mask 不会消失: 这个加个状态标识就好了: 此外,还有两个小问题: 一个是在窗口改变大小的时候,没有重新计算 mask 样式: 这个 Mask 组件里用 ResizeObserver

    11210

    图解浏览器的各种距离

    比如 OnBoarding 组件,我们要拿到每一步的高亮元素的位置、宽高: 比如 Popover 组件,需要拿到每个元素的位置,然后确定浮层位置: 比如滚动页面底部,触发列表的加载,这需要拿到滚动的距离和页面的高度...首先,页面一般都是超过一屏的,右边会出现滚动条,代表当前可视区域的位置: 这里窗口的部分是可视区域,也叫做视口 viewport。 如果我们点击了可视区域内的一个元素,如何拿到位置信息呢?...因为这里要介绍一个 react 事件的坑点: react 事件是合成事件,所以它少了一些原生事件的属性,比如这里的 offsetY,也就是点击的位置距离触发事件的元素顶部的距离。...import { MouseEventHandler, useEffect, useRef } from 'react' function App() { const ref = useRef<HTMLDivElement...import { useEffect, useRef } from 'react' function App() { const ref = useRef(null

    13510

    使用react-hooks事件监听中state不更新问题

    ,是有滚动条的,当你点击按钮时,会依次打印出count自增前的值,但是当你滚动页面时,你会发现这个count始终是1,无论怎么点击都不变,让人很好奇,为什么click事件可以拿到最新的count值,但是监听事件中拿不到呢...关键点是在于useEffect,这个useEffect形成了一个闭包,而且其中的闭包只App组件第一次渲染的时候执行, 这个闭包的外部作用域就是上面的obj对象。...点击按钮,调用setCount触发App组件重新渲染,App函数会重新执行,此时通过useState拿到最新的count值为2。...App重新渲染时,useEffect内的闭包并不会执行,监听事件中拿到的count始终是第一次App执行的时候生成的作用域对象的count属性值1, 拿不到最新的count值。...,我们可以监听事件中使用setCount,对于count变化具体的执行放在useEffect中即可。

    7.1K30

    React 进阶 - 海量数据处理和其他细节

    ,都显示页面上,如果伴随着数据量越来越大,会使页面中的 DOM 元素越来越多,即便是像 React 可以良好运用 diff 来复用老节点,但也不能保证大量的 diff 带来的性能开销。...虚拟列表,长列表滚动过程中,只有视图区域显示的是真实 DOM ,滚动过程中,不断截取视图的有效区域,让人视觉上感觉列表是滚动,达到无限滚动的效果。...(除了缓冲区),剩下的区域,不需要渲染真实的 DOM 元素 虚拟列表就是通过这个方式来减少页面上 DOM 元素的数量 实现思路 通过 useRef 获取元素,缓存变量 useEffect 初始化计算容器的高度...,可视区域要向上滚动,当用户向上滑动的时候,可视区域要向下滚动 通过重新计算 end 和 start 来重新渲染列表 代码实现 function VirtualList() { const [dataList...但是 React 中只要触发 setState 或 useState ,如果没有渲染控制的情况下,组件就会渲染,暴露一个问题就是,如果视图更新不依赖于当前 state ,那么这次渲染也就没有意义。

    1.4K10

    精读《正交的 React 组件》

    让组件与滚动监听正交 比如一个滚动到一定距离就出现 "jump to top" 的组件 ,可能会这么实现: import React, { useState, useEffect...如果我们将 “滚动到一定距离就渲染 UI” 抽象成通用组件 IfScrollCrossed 呢?...import { useState, useEffect } from "react"; function useScrollDistance(distance) { const [crossed...; } 虽然将取数生命周期封装到自定义 hook useSWR 中,但 error 信息对 UI 组件来说就是一个脏数据:这让这个 UI 组件不仅要渲染数据,还要担心取数是否会失败,或者是否...因为取数状态 Suspense 管理,而取数是否意外失败由 ErrorBoundary 管理。 合理的抽象使组件逻辑变得更简单,从而组件嵌套使用使不用担心额外影响。

    56620

    懒加载 React页面 - 动态渲染组件

    在这种情况下,如果一次性将页面全部渲染,可想而知,我们的页面直出效率(fmp, fid)会受到影响。 为了更好的用户体验,我们需要考虑在用户滚动到下一屏时,渲染下一屏的组件。 ?...Loading 组件是否视图内 如图 1 所示,当 loading 组件的位置滚动到视图中时,并且如果此时还有未渲染的组件,这时便是渲染下一屏的时机。...监听滚动优化 滚动时会频繁触发 scrollRenderHandler 函数,导致页面性能低下。...这意味着,在窗口滚动的过程中,我们反复更新了 compList 数据,从而导致了楼层组件重新渲染,而每个楼层组件的数据请求,是放在组件内部的,这与该楼层的唯一标识 uuid 相关,因此导致数据接口的重复请求...写一个普通的长页面的过程中,如果只追求完成,那么将会非常简单,但如果想要进一步优化,那可做的事情就有很多了。

    3.4K20

    源码工作台:如何提效业务源码开发

    对于ajax 接口联调一般都是 componentDidMount 或者 useEffect 中。虽说如此,但是比较宽泛。...boolean toTopProps 回到顶部组件的属性 IScrollToTopProps renderHeader 渲染头部组件 () => FunctionComponent renderFootr...触底事件 RESET_SCROLL 重置滚动重新计算容器高度 ENABLE_SCROLL 禁止滚动 true/fase 如上容器组件的封装,就提供了基本的容器能力。...有了基础容器提供的底层能力,再回想我们使用 react、vue 还是 rax 开发前端页面,其实都是「状态驱动 UI 的过程」 ,所以针对复杂业务的场景,状态管理自然必不可少。...❝源码架构初始化出来是一个模拟的请求,数据来自 「page-name/mock/index.json」 ❞ 状态分发 use-data-init.ts 自定义 hooks 中,拿到数据,根据「

    56030

    使用 React 和 Tailwind 创建阅读进度条

    目录 前言 实现逻辑 代码 样式 前言 我们在上网的时候经常会看到一些优秀的博客顶部有个进度条,这个进度条有助于读者衡量阅读进度,我认为这个功能可以带来良好的用户体验,所以,应该将其添加到我个人博客上的文章中...实现逻辑 获取页面可以滚动的高度. 获取页面已经滚动的高度....阅读进度=已经滚动的高度/页面可以滚动的高度 代码 单独定义一个 react hook 来活动当前的阅读进度 import { useEffect, useState } from 'react' export...window.removeEventListener('scroll', updateScroll) } }, []) return progress } 剩下的工作是将进度显示页面上...,为此,我顶部的导航栏上显示一个进度条。

    77620

    useLayoutEffect的秘密

    「延迟加载」:将不是立即需要的资源推迟加载,比如在页面滚动到特定位置或用户执行某些操作时再加载。...} ) } 现在,state用实际数字更新,它将触发导航的重新渲染React重新渲染项目并删除那些不可见的项目。 6....对于其他所有情况,useEffect 是更好的选择。 ❞ 对于useEffect有一点我们需要额外说明一下。 ❝大家都认为 useEffect浏览器渲染触发,其实不完全对。...❞ useEffect 有时渲染前执行 正常的流程中,React 更新过程如下: React工作:渲染虚拟DOM,安排effect,更新真实DOM 调用 useLayoutEffect React...下面是一个时间轴: React 更新 1:渲染虚拟DOM,安排effect,更新DOM 调用 useLayoutEffect 更新state,安排重新渲染(re-render) 调用 useEffect

    23610
    领券