Created
February 9, 2025 01:24
-
-
Save zacharytyhacz/3fe831a062f0713aaea41e9c649dbba6 to your computer and use it in GitHub Desktop.
react native useResponsiveStyles.ts hook
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useMemo, useCallback } from 'react' | |
import { | |
useWindowDimensions, | |
StyleSheet, | |
ViewStyle, | |
TextStyle, | |
ImageStyle | |
} from "react-native"; | |
const BREAKPOINTS = { | |
mobile: 0, | |
tablet: 768, | |
desktop: 1024, | |
}; | |
// Define allowed style types | |
type StyleObject = ViewStyle | TextStyle | ImageStyle; | |
// Ensure `mobile`, `tablet`, `desktop` must have the same keys as `shared` | |
type ResponsiveStyles<T extends Record<string, StyleObject>> = { | |
base: T; | |
mobile?: Partial<{ [K in keyof T]: StyleObject }>; | |
tablet?: Partial<{ [K in keyof T]: StyleObject }>; | |
desktop?: Partial<{ [K in keyof T]: StyleObject }>; | |
}; | |
export function useResponsiveStyles<T extends Record<string, StyleObject>>(styles: ResponsiveStyles<T>) { | |
const { width } = useWindowDimensions(); | |
// Merge shared styles as base for each key | |
const mergeStyles = useCallback((base: T, override?: Partial<{ [K in keyof T]: StyleObject }>): T => { | |
const result: Partial<T> = { ...base }; | |
if (override) { | |
for (const key in base) { | |
result[key] = { ...base[key], ...(override[key] || {}) }; | |
} | |
} | |
return result as T; | |
}, []) | |
const generatedStyles = useMemo(() => { | |
let responsiveStyles: T = styles.base; | |
if (width >= BREAKPOINTS.tablet && styles.tablet) { | |
responsiveStyles = mergeStyles(responsiveStyles, styles.tablet); | |
} | |
if (width >= BREAKPOINTS.desktop && styles.desktop) { | |
responsiveStyles = mergeStyles(responsiveStyles, styles.desktop); | |
} | |
if (width < BREAKPOINTS.tablet) { | |
responsiveStyles = mergeStyles(responsiveStyles, styles.mobile); | |
} | |
return StyleSheet.create(responsiveStyles) as T; | |
}, [width, styles]); | |
return generatedStyles; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment