A React hook (>=16.8) for getting the current responsive media breakpoint, successor to breakpoint-observer.
Initialize useBreakpoint
with a configuration object, and optionally a default breakpoint name (in non-window environments like SSR). The return value will be an object with the breakpoint's name (string
), min-width, and max-width values (number
):
import useBreakpoint from 'use-breakpoint';
/**
* It is important to bind the object of breakpoints to a variable for memoization to work correctly.
* If they are created dynamically, try using the `useMemo` hook.
*/
const BREAKPOINTS = { mobile: 0, tablet: 768, desktop: 1280 }
const CurrentBreakpoint = () => {
const { breakpoint, maxWidth, minWidth } = useBreakpoint(BREAKPOINTS, 'desktop');
return <p>The current breakpoint is {breakpoint}!</p>;
};
Given a configuration BREAKPOINTS = { mobile: 0, tablet: 768, desktop: 1280 }
and a window size of 1280x960
, the hook will return as the breakpoint:
const { breakpoint } = useBreakpoint(BREAKPOINTS)
undefined
when rendered server-side'desktop'
when rendered client-side
const { breakpoint } = useBreakpoint(BREAKPOINTS, 'mobile')
'mobile'
when rendered server-side'mobile'
on the first client-side render'desktop'
on subsequent client-side renders
const { breakpoint } = useBreakpoint(BREAKPOINTS, 'mobile', false)
'mobile'
when rendered server-side'desktop'
when rendered client-side
If supplied a default breakpoint, the hook will always return that value when rendered server-side. To not cause inconsistencies during the first client-side render, the default value is also used client-side for the first render, instead of the (possibly different) real breakpoint.
For example, given a breakpoint config:
const { breakpoint } = useBreakpoint(BREAKPOINTS, 'mobile')
When rendered server-side, breakpoint === 'mobile'
always, because there is no window.
On client-side with a desktop
-sized window, on the first render breakpoint === 'mobile'
, and then on following renders breakpoint === 'desktop'
.
This is to ensure ReactDOM.hydrate
behaves correctly.
To disable this behavior, pass false
as the third argument:
const { breakpoint } = useBreakpoint(BREAKPOINTS, 'mobile', false)
Now breakpoint === 'mobile'
server-side, but breakpoint === 'desktop'
client-side during the first render. You should probably use ReactDOM.render
instead of ReactDOM.hydrate
in this case.
This hook uses the window.matchMedia functionality to calculate the current breakpoint. For a list of breakpoints, we generate some css media queries in the form of (min-width: XXXpx) and (max-width: YYYpx)
and then add listeners for the changes. useBreakpoint
will then update its return value when the breakpoint changes from one rule to another.
This project is built with Typescript. A Storybook is included for local previewing. The easiest way to get started is cloning the repo and starting the storybook server locally via npm start
.