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?