Skip to content

Instantly share code, notes, and snippets.

@gchumillas
Last active March 17, 2024 13:41
Show Gist options
  • Save gchumillas/8ff484d74a32df26ef70dba91adf6256 to your computer and use it in GitHub Desktop.
Save gchumillas/8ff484d74a32df26ef70dba91adf6256 to your computer and use it in GitHub Desktop.
breakpoints hook
import { useCallback, useMemo, useEffect } from 'react'
export const useBreakpoints = <T extends Record<string, number>>(breakpoints: T): keyof T | undefined => {
const searchBreakpoint = useCallback((breakpoints: { key: string, value: number }[]) => {
return breakpoints.find((x) => window.innerWidth < x.value)?.key
}, [])
const entries = useMemo(() => {
return Object
.entries(breakpoints)
.sort((a, b) => a[1] - b[1])
.map(([key, value]) => ({ key, value }))
}, [breakpoints])
const [breakpoint, setBreakpoint] = useState(searchBreakpoint(entries))
useEffect(() => {
const onResize = () => {
setBreakpoint(searchBreakpoint(entries))
}
window.addEventListener('resize', onResize)
return () => {
window.removeEventListener('resize', onResize)
}
}, [entries, searchBreakpoint])
return breakpoint
}
import React from 'react'
import { useBreakpoints } from './use-breakpoints.ts'
// I recommend to declare breakpoints somewhere outside the component
// to prevent unnecessary re-renders.
//
// Otherwise don't forget to wrap it around React.useMemo:
// useBreakpoints(React.useMemo({ sm: 640, md: 768, ... }))
const breakpoints = {
sm: 640,
md: 768,
lg: 1024,
xl: 1280
}
function App() {
const size = useBreakpoints(breakpoints)
if (size == 'sm') {
return <p>Small device.</p>
} else if (size == 'md') {
return <p>Medium device.</p>
} else if (size == 'lg') {
return <p>Large device.</p>
} else if (size == 'xl') {
return <p>Very large device.</p>
}
return (
<p>Extra large device!</p>
)
}
export default App
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment