对于同一个页面,数据改变,然后使用setState更新状态,页面位置会变吗?

#1

使用react做的单页应用,首页是一个列表,当滚动到底部后,重新向服务器请求更多的数据,然后setState
发现页面会记住当前浏览的位置。
问题:当setState后,不是会重新渲染吗?然后应该回到页面顶部了呀。

#2

不知道是不是因为这样的原因,比如列表代码结构:


1
2
3


当服务器数据重写请求的时候,dom中page、list都没有更新,还是原来的dom结构,只更新了item中的数据,所以才导致滚动条并没有滚动到页面顶部。。。可以重新render整个列表,或ele.scrollTop=0.

#3

你的setState是每次在原有的data上concat新的数据自然会依次往下加载,你本身的列表组件没有被销毁是不会整个重新渲染的,setState只会渲染每次新加的部分。

1 Like
#4

页面会记住当前浏览的位置,这行为称为:Scroll Restoration。
这是浏览器的默认行为,这一特性在传统多页中是很贴心的。不过在 SPA 就不那么友好了。在 SPA 中,后退时也能Scroll Restoration,但实际情况会存在如下问题:

SPA 是客户端渲染,在浏览器试图执行Scroll Restoration时,页面可能还没被渲染好(或异步加载渲染)。这样会导致在页面渲染完后,不能滚动到之前正确的位置。

解决方法

  1. 避免使用 window 滚动,采用一个内部可滚动的容器 div 方式。不过这样会丢失一些浏览器默认功能,如滑动隐藏顶部地址栏。
  2. 在浏览器Scroll Restoration之后,通过二次滚动重写浏览器的自动滚动恢复。 但这样会存在明显页面跳动,用户体验不是很好。不过 Facebook, medium 都是采用这种修复方案。其实这里可以通过history.scrollRestoration禁掉默认行为,这样用户体验会更好:
if ('scrollRestoration' in history) {
  // Back off, browser, I got this...
  history.scrollRestoration = 'manual';
}

另外,还存在当setState后,不会重新渲染问题(你描述的问题不是太清晰)?
一般出现列表不渲染问题,都与virtual dom的diff算法有关。添加一个唯一key都能解决问题。

#5

我要实现的是滚动加载的功能,页面滚动到底部后,向服务器请求数据,然后更新状态,此时页面会将新拿到的数据加载到页面上。
我本来以为setState会触发重新渲染整个页面,然后会回到 页面顶部,但是实事是页面位置不变,停留在向服务器请求数据前的位置。

#6

不会啊,为什么会回到页面顶部呢?