SDK methods in Gatsby without referencing window

I want to run methods from the SDK for example I want the cart to programmatically be populated with an array of items. The only way I seem able to access the Snipcart object is by directly referencing window. With a Gatsby project when I try to deploy and build it with Netlify it breaks because it can not access window, “window is not available during server side rendering.”

Is there any work around to this or way to access Snipcart object without referencing window?

Thanks so much. I’ve pasted an example bit of code in which I’m referencing the snipcart object with window:

    const addCart = async () => {
      try {
        if (filteredProducts.length > 0) {
          await filteredProducts.forEach(product => {
            window.Snipcart.api.cart.items.add({
              id: product.node.id,
              name: product.node.name,
              price: product.node.price,
              url: `https://modest-curran-c90323.netlify.app/shop/${product.node.slug}`,
              quantity: 1,
            })
          })
        } else {
          return
        }
      } catch (e) {
        console.log(e)
      }
    }

In case anyone encounters this issue, I seemed to have solved it by wrapping the offending code in a if ( typeof window !== “undefined”) statement as suggested in this blog:

This worked for me to get past the build error and the live site functions properly. Yay.

1 Like

Using if (typeof window !== "undefined") will do the trick.

If you want a more robust solution, I wrote a context provider for my Snipcart instance:

import React, { useState } from "react"

export const SnipcartContext = React.createContext()

export const SnipcartProvider = ({ children }) => {
  const [snipcartReady, setSnipcartReady] = useState(false)

  React.useEffect(() => {
    const listenSnipcart = () => {
      document.addEventListener("snipcart.ready", () => {
        setSnipcartReady(true)
      })
    }
    
    if (typeof window !== "undefined") {  // don't run for SSR builds
      if (window.Snipcart !== undefined) {
        setSnipcartReady(true)
      } else {
        listenSnipcart()
      }
    }
  }, [])

  return (
    <SnipcartContext.Provider value={{ snipcartReady, snipcartApi }}>
      {children}
    </SnipcartContext.Provider>
  )
}

Then, in a component that is wrapped by the SnipcartProvider:

export const SnipcartMetadata = () => {
  const { user, isLoading } = useAuth0()
  const { snipcartReady } = useContext(SnipcartContext)

  useEffect(() => {
    if (snipcartReady) {
      // Do something with window.Snipcart after it is available
    }
  }, [snipcartReady])

  return null
}