Answer specific to Next.js
Since you are using Next.js window isn't defined until the code is run on the client side. As this question suggests, try setting an initial width on an useEffect hook like this:
useEffect(() => setWindowSize(window.innerWidth), [])
Observe the empty brackets meaning the hook will be executed once on every render, which in this case means once it renders on the client's side.
Answer not specific to Next.js
In your hook, initialize it to window.innerWidth instead of null.
const [width, setWidth] = useState<number>(window.innerWidth)
Other observations
Also, I would suggest you set up a listener for resize on a separate useEffect hook because the way it is right now the listener depends on windowSize changing before being attached. Take for example this useIsVertical hook:
const useIsVertical = () => {
const [isVertical, setIsVertical] = useState(false)
const onResize = () => {
const height = window.innerHeight
const width = window.innerWidth
height > width ? setIsVertical(true) : setIsVertical(false)
}
useLayoutEffect(() => {
onResize()
}, [])
useLayoutEffect(() => {
window.addEventListener('resize', onResize)
return () => window.removeEventListener('resize', onResize)
}, [])
return isVertical
}