简体   繁体   中英

Use GraphQL data in gatsby-browser?

I have an app with some route ID's (basically a bunch of sections in a long SPA) that I have defined manually. I fetch these in gatsby-browser.js and use them in conjunction with shouldUpdateScroll , checking if the route ID exist, and in that case, scroll to the position of the route/section.

Example:

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
}

This works well for my usecase.

Now I want to add something similar for a page where the content is dynamically created (fetched from Sanity). From what I understand I cannot use GraphQL in gatsby-browser.js , so what is the best way to get the ID's from Sanity to gatsby-browser.js so I can use them to identify their scroll positions?

If there's some other better way to achieve the same result I'm open to that of course.

I think that you are over complexing the issue. You don't need the gatsby-browser.js to achieve it.

  • First of all, because you are accessing directly to the DOM objects (using document.getElementById ) and you are creating precisely a virtual DOM with React to avoid pointing the real DOM. Attacking directly the real DOM (like jQuery does) has a huge performance impact in your applications and may cause some issues since in the SSR ( S erver- S ide R endering) the element may not be created yet.

  • You are hardcoding a logic part (the id s) on a file that is not intended to do so.

I think you can achieve exactly the same result using a simple function using a few hooks.

You can get the same information as document.getElementById using useRef hook and scrolling to that position once needed.

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>
    </>
  );
}

You can isolate that function into a separate file in order to receive some parameters and return some others to achieve what you want. Basically, the snippet above creates a reference for each section and, once the DOM tree is loaded ( useEffect with empty deps , [] ) do some stuff based on your logic.

Your document.getElementById is replaced for sectionOne.current (note the .current ), initially set as null to avoid unmounting or cache issues when re-hidration occurs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM