diff --git a/src/index.tsx b/src/index.tsx index 3a063ec..eb7959d 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -3,9 +3,8 @@ import { useContext, useState, useEffect } from 'react' type MQListEventListener = (this: MediaQueryList, ev: MediaQueryListEvent) => void -type GetCurrentZone = (FullBreakpoints: number[], defaultZone: number) => number -export const getCurrentZone: GetCurrentZone = (bps, defaultZone) => { - if (typeof window === 'undefined') return defaultZone +type GetCurrentZone = (FullBreakpoints: number[]) => number +export const getCurrentZone: GetCurrentZone = (bps) => { const width = window.innerWidth let outZone = bps.findIndex(bp => width < bp) if (outZone < 0) outZone = bps.length @@ -16,7 +15,7 @@ type GetMediaQueryLists = (FullBreakPoints: number[]) => MediaQueryList[] const getMqLists: GetMediaQueryLists = (bps) => bps.map((bp, i) => { const nextBp = bps[i + 1] return window.matchMedia( - `(min-width: ${bp}px) ${nextBp ? `and (max-width: ${nextBp}px)` : ''}` + `(min-width: ${bp}px) ${nextBp ? `and (max-width: ${nextBp - 1}px)` : ''}` ) }) @@ -35,9 +34,13 @@ export const ZoneManager: React.FC = ({ children }) => { const bps = [0, ...breakpoints] - const [zone, setZone] = useState(getCurrentZone(bps, defaultZone)) + // SSR renders without calling `useEffect` hooks (thus falling back to `defaultZone`), that's + // why we need to render with the `defaultZone` on the client first to re-hydrate the dom + const [zone, setZone] = useState(defaultZone) useEffect(() => { + setZone(getCurrentZone(bps)) + const listenerForZone = (i: number):MQListEventListener => (e) => { if (!e.matches) return setZone(i) @@ -54,7 +57,10 @@ export const ZoneManager: React.FC = ({ return () => { mqLists.forEach((mqList, i) => mqList.removeListener(listeners[i])) } - }, [bps]) + }, + + // We use the whole bps array as deps. Using `[bps]` would re-execute `useEffect` on each render + bps) return {children} }