如何修复 Gatsby JS Link 组件保留滚动位置而不重置到顶部

Posted

技术标签:

【中文标题】如何修复 Gatsby JS Link 组件保留滚动位置而不重置到顶部【英文标题】:How to fix Gatsby JS Link component retaining scroll position and not resetting to top 【发布时间】:2019-08-15 15:17:26 【问题描述】:

我正在使用 Gatsby 2.2.10 设置网站,并且链接组件保留上一页的滚动位置,并且在单击它们时不会滚动回顶部。

<div className="Footer__legal body">
 <p>© new Date().getFullYear() My Nice Company</p>
 <Link to="/privacy-policy">Privacy Policy</Link>
 <Link to="/page-2">Page 2 Link component</Link>
</div>

预期行为:

当您点击“隐私政策”、“第 2 页”或网站底部的任何页面时,我希望页面加载时用户回到顶部。

实际行为:

用户停留在当前页面的滚动位置

【问题讨论】:

Repo 和 netlify 链接不可用。 【参考方案1】:

你也可以修改gatsby-browser.js,为每次滚动更新实现一个钩子:

// in gastby-browser.js
exports.shouldUpdateScroll = (
  routerProps:  location ,
  getSavedScrollPosition,
) => 
  const  pathname  = location
  // list of routes for the scroll-to-top-hook
  const scrollToTopRoutes = [`/privacy-policy`, `/page-2`]
  // if the new route is part of the list above, scroll to top (0, 0)
  if (scrollToTopRoutes.indexOf(pathname) !== -1) 
    window.scrollTo(0, 0)
  

  return false

您可以在 GatsbyJS 网站上的 shouldUpdateScroll on GitHub 或 documentation for shouldUpdateScroll 中找到代码。

【讨论】:

这对你有用吗?我没有运气。我打开的任何链接都会将我带到与上一页相同的向下滚动的新路线。 @jj0b 您是否重新启动了 gatsby 命令? gatsby-config.jsgatsby-browser.js 等的更改在重新启动开发/服务/构建过程后生效。 我做到了。最终对我有用的是使用 document.getElementById("WhateverIdYouWantToScrollTo").scrollIntoView() 而不是 window.scrollTo(0,0)。我碰巧在 useEffect 钩子中使用它,但我确信在正确的时间触发该行的任何其他方法都可能对我有用。更多细节在这里:***.com/questions/33188994/… 这行得通,我只是把window.scrollTo() 无条件地放在了所有页面导航上。【参考方案2】:

如果你在body 上设置了overflow: hiddenoverflow: auto,你就会遇到这个问题!

【讨论】:

欢迎您,感谢您的贡献。请考虑使用“编辑”来更新您的帖子,以解释发生这种情况的原因,或者提供指向表明这是已定义/预期行为的文档的链接。 这实际上是对我的修复——我的身体溢出了:auto。我不确定为什么会这样,但希望有人可以帮助解释原因。【参考方案3】:

如果你的页面是一个无状态的功能组件,你可以使用useEffect 钩子来滚动回到页面顶部,假设你正在使用graphql 并且你的组件需要一些数据作为参数。这样每次data 发生变化时,您都会滚动到页面顶部(类似于componentDidUpdate)。

const PageCmp = ( data ) => 
    ...
    useEffect(() => 
        window.scrollTo(0,0)
    , [data])
    ...

【讨论】:

【参考方案4】:

想出一个解决方法,将 index.js 页面转换为基于类的组件,然后添加

  componentDidUpdate() 
    window.scrollTo(0,0);
  

不是最干净的解决方法,我也不知道为什么它没有自动滚动,下周去参加一个 JS 聚会,然后我会问这个问题,如果我得到答案,我会发布跟进。

我觉得这与我的风格有关,因为我开始了一个新项目并且 Gatsby-cli 没有任何问题。将重构样式,看看这是否能解决问题。

注意:回到 Michael 的回答之后,这也与我身上的 overflow: hidden; 风格有关,删除这也解决了我的问题。

【讨论】:

回到上面迈克尔的回答之后,它也与我身上的overflow: hidden; 风格有关,删除它也解决了我的问题。 我很高兴,我能帮上忙。我想提一点:与其添加评论,不如考虑编辑您的答案并添加类似“注意:... @JackDavidEvans - 我遇到了这个问题,我确实有溢出:隐藏在我的身上!删除它为我解决了这个问题!非常感谢!【参考方案5】:

好的,这是一个老问题,但我最近也遇到了同样的奇怪行为。事实证明,我的问题与迄今为止我在互联网上看到的所有其他解决方案都不同。

Gatsby 使用了一个名为 gatsby-react-router-scroll 的包。这个包管理 Gatsby 的滚动行为。此行为主要在Scroll Handler 组件中实现。该组件仅在componentDidUpdate 方法中向上滚动,而不在componentDidMount 方法中向上滚动。我在componentDidMount 方法中添加了一个debugger,并且每次导航都会重新安装ScrollHandler 组件。

解决方法是弄清楚为什么在每次导航时都会安装和重新安装这个组件。就我而言,我的gatsby-browser.js 中的wrapRootElement 函数上有一个React.StrictMode 组件。删除 StrictMode 使 ScrollHandler 组件稳定,从而解决了我的问题。

【讨论】:

【参考方案6】:

useEffect(() =&gt; window.scrollTo(0, 0), []) 为我解决了这个问题。我只在 Firefox 上遇到问题,但在 chrome 上没有。我知道是什么导致了这个问题,但现在可以正常工作了。

【讨论】:

【参考方案7】:

我的问题是我有html height: 100%。删除该规则似乎已经解决了问题。

我的项目中还有gatsby-plugin-transition-link,它为我的主要内容添加了更多包装器。

【讨论】:

【参考方案8】:

在我的 CSS 中,我有

html, body 
  height: 100%;
  overflow-y: scroll;

因为这是修复仅限移动设备的 safari 错误的唯一方法(我的最爱!)

如果您也无法摆脱overflow 属性,我建议这样做:

// in gatsby-browser.js
export function shouldUpdateScroll(prevRouterProps,  location ) 
  window.scrollTo(0, 0)
  const body = document.getElementsByTagName('body')[0]
  body.scrollTop = 0
  return false

【讨论】:

以上是关于如何修复 Gatsby JS Link 组件保留滚动位置而不重置到顶部的主要内容,如果未能解决你的问题,请参考以下文章

样式化的组件,带有 gatsby-link 锚标签 css 着色

如何修复 gatsby_1 未定义

javascript Gatsby / Contentful - link.js

GraphQL - Gatsby.js- React 组件。 - 如何查询变量/参数?

如何在 gatsby 中创建动态路由

Gatsby Link 重置 Apollo 客户端