【问题标题】:Use GraphQL data in gatsby-browser?在 gatsby-browser 中使用 GraphQL 数据?
【发布时间】:2021-03-25 06:09:43
【问题描述】:

我有一个应用程序,其中包含我手动定义的一些路线 ID(基本上是长 SPA 中的一堆部分)。我在gatsby-browser.js 中获取这些并将它们与shouldUpdateScroll 结合使用,检查路线ID 是否存在,在这种情况下,滚动到路线/部分的位置。

例子:

export const shouldUpdateScroll = ({ routerProps: { location } }) => {
  const container = document.querySelector('.site')
  const { pathname } = location
  
  const projectRoutes = [`project1`, `project2`]
  if (projectRoutes.indexOf(pathname) !== -1) {
      const target = document.getElementById(pathname)
      container.scrollTop = target.offsetTop; 
  }

  return false
}

这很适合我的用例。

现在我想为动态创建内容(从 Sanity 获取)的页面添加类似的内容。据我了解,我无法在 gatsby-browser.js 中使用 GraphQL,那么将 ID 从 Sanity 获取到 gatsby-browser.js 以便我可以使用它们来识别它们的滚动位置的最佳方法是什么?

如果有其他更好的方法可以达到同样的效果,我当然愿意。

【问题讨论】:

    标签: javascript node.js reactjs graphql gatsby


    【解决方案1】:

    我认为你把问题复杂化了。你不需要gatsby-browser.js 来实现它。

    • 首先,因为您正在直接访问 DOM 对象(使用 document.getElementById)并且您正在使用 React 创建精确的虚拟 DOM 以避免指向真实的 DOM。直接攻击真实的 DOM(就像 jQuery 一样)会对您的应用程序的性能产生巨大影响,并且可能会导致一些问题,因为在 SSR (Server-Side R渲染)该元素可能尚未创建。

    • 您在不打算这样做的文件上硬编码逻辑部分(ids)。

    我认为你可以通过几个钩子使用一个简单的函数来获得完全相同的结果。

    您可以使用useRef 钩子获得与document.getElementById 相同的信息,并在需要时滚动到该位置。

    const YourComponent= (props) => {
      const sectionOne = useRef(null);
      const sectionTwo = useRef(null);
    
      useEffect(()=>{
       if(typeof window !== `undefined`){
        console.log("sectionOne data ",sectionOne.current)
        console.log("sectionTwo data ",sectionTwo.current)
          if(sectionOne) window.scrollTo( 0, 1000 ); // insert logic and coordinates 
       }
      }, [])   
    
      return (
        <>
          <section ref={sectionOne}>Section 1</section>
          <section ref={sectionTwo}>Section 2</section>
        </>
      );
    }
    

    您可以将该函数隔离到一个单独的文件中,以便接收一些参数并返回一些其他参数以实现您想要的。基本上,上面的 sn-p 会为每个部分创建一个引用,一旦加载了 DOM 树(useEffect 和空的deps[]),就会根据你的逻辑做一些事情。

    您的document.getElementById 被替换为sectionOne.current(注意.current),最初设置为null 以避免在重新隐藏时出现卸载或缓存问题。

    【讨论】:

    • 感谢您的回答。你的建议很有道理。我已经逐渐重写了我的应用程序的工作方式,在这一点上,也许我应该按照你建议的方式完全重写。我会尽快尝试一下,看看我是否能实现我所需要的。一旦我这样做,我将重新审视您的答案并将其标记为解决方案。再次感谢!
    • 不错。请记住在使用全局对象时使用typeof window !== 'undefined'。您可以在gatsbyjs.com/docs/debugging-html-builds中找到更多详细信息
    • 我用来导航到这些部分的菜单是全局的,所以我可以在另一个页面上单击菜单中的项目名称,它应该会更改路线并识别并转到该部分。您认为,我是否应该在 HoC/上下文中有一个状态来保存单击的菜单项的 ID,然后在路由更改时对其进行操作?
    猜你喜欢
    • 2020-03-24
    • 2020-09-24
    • 2020-06-02
    • 2021-07-01
    • 2021-03-18
    • 2019-10-12
    • 2021-03-29
    • 2020-11-20
    • 2019-03-02
    相关资源
    最近更新 更多