After deployment to server and testing in Gatsby with gatsby clean && gatsby build && gatsby serve whenever root (https://foobar.com/) is visited anything that relies on my ThemeProvider for dimensions doesn't render correctly.
After debugging I've isolated my issue down to how my useState is hard set with a value of 0:
const [size, setSize] = useState({
windowWidth: hasWindow ? window.innerWidth : 0,
windowHeight: hasWindow ? window.innerHeight : 0,
})
full code:
import { useState, useEffect } from 'react'
const hasWindow = typeof window !== 'undefined'
const useWindowDimensions = () => {
const [size, setSize] = useState({
windowWidth: hasWindow ? window.innerWidth : 0,
windowHeight: hasWindow ? window.innerHeight : 0,
})
const updateSize = () =>
setSize({
windowWidth: window.innerWidth,
windowHeight: window.innerHeight,
})
useEffect(() => (window.onresize = updateSize), [])
return size
}
export default useWindowDimensions
which gets passed to my ThemeProvider:
import React, { createContext } from 'react'
// Utils
import useWindowDimensions from '../utils/useWindowDimensions'
const defaultContext = {
windowWidth: 0,
windowHeight: 0,
}
export const ThemeContext = createContext(defaultContext)
const ThemeProvider = ({ children }) => {
const { windowWidth, windowHeight } = useWindowDimensions()
return (
<ThemeContext.Provider value={{ windowWidth, windowHeight }}>{children}</ThemeContext.Provider>
)
}
export default ThemeProvider
and if I hard set my useState values:
const [size, setSize] = useState({
windowWidth: hasWindow ? window.innerWidth : 1600,
windowHeight: hasWindow ? window.innerHeight : 1600,
})
my site renders fine in the browser but this is technically wrong if viewed with a mobile device or the browser is smaller than 1600px. Whenever I navigate to anywhere else in the site the useState is updated and there isn't an issue.
Omitting the ternary check for window and hard setting useState to:
const [size, setSize] = useState({
windowWidth: window.innerWidth,
windowHeight: window.innerHeight,
})
produces an expected server rendering error:
"window" is not available during server side rendering.
after gatsby build.
How should I be setting my useState window dimensions after server load so that my site will pass the correct values to the ThemeProvider and render everything correctly when root is visited?
Please try this slight modification and let me know if that works. In your
useWindowDimensionscustom hook:Your
Context: