React.js:停止呈现滚动到页面顶部

React.js: Stop render from scrolling to top of page

每次在 React.js 中执行渲染时,UI 都会滚动到页面顶部。

JSFiddle:http://jsfiddle.net/bengrunfeld/dcfy5xrd/

有什么漂亮的或被动的方法来阻止它吗?

例如如果用户向下滚动页面,然后按下导致呈现的按钮,UI 将保持在与以前相同的滚动位置。

// Forces a render which scrolls to top of page
this.setState({data: data});

更新:为什么 UI 滚动到某些渲染的顶部,而不是其他渲染?

@floydophone 在 Twitter 上回答了这个问题。

https://twitter.com/floydophone/status/608129119025561600

@bengrunfeld @reactjs you forgot preventDefault() on your link handlers

想在这里给那些没有使用锚标签的人补充,preventDefault不会拯救你。尽管很奇怪,但对我来说,这与在 div

中渲染我的子组件有关
display:table > display:tablecell

由于某种原因,在这种情况下,当有任何重新渲染时,子组件的滚动位置会丢失。当我切换到 flexbox (display:flex) 时问题消失了。

好的,如果有人读到这篇文章,就我而言,问题不在于以上任何一个。您必须先尝试以上任何方式的建议。我做了一切,包括 preventDefault() 但没有帮助我。问题是;使用 styled-components。因为,styled-components 给每个渲染一个随机的 class 名称。所以它重置滚动。我从 css 中给出了 class 名称并解决了我的问题。

如果渲染触发器滚动到顶部,通常意味着某些 UI 组件由于状态而改变其尺寸,这可以通过添加最小值 width/height

来解决

发生这种情况的原因可能是 redux 状态发生了变化,它会在使用它的代码中随处显示变化。 尝试使用该组件的本地状态进行更改,页面正在滚动。

2022 Hacky 解决方案:

我找不到完全阻止 re-render 滚动的方法。 preventDefault没有帮助,我没有访问到具体的元素结构,但我确实有滚动元素的className。

useEffect(() => {
  const el = document.getElementsByClassName('my-classname')?.[0];
  const newTimeoutRef = setTimeout(() => el?.scrollTo(0, scrollTop), 50);
  return () => clearTimeout(newTimeoutRef);
}, [scrollTop]);

然后在之前导致滚动到顶部的事件中设置 scrollTop(作为组件状态)。

这里的 hack 是 setTimeout,它基本上让 DOM 有时间在调用你的 el.scrollTo 之前滚动到顶部,它闪烁了一下,但它是最好的对我有用的解决方案。