ifit/ hooks
2020 - typescript, react
A private React hooks library created to make custom hooks to be shared with multiple webview applications at iFit. I created the "useMedia" hook which provides a JavaScript level media query for styles and rendering.
useMedia:
import { ReactNode, useState, useEffect, useCallback, useMemo } from "react"
export const media = {
phoneMax: "(max-width: 767px)",
tablet7Min: "(min-width: 768px)",
tablet7Max: "(max-width: 1024px)",
tablet10Min: "(min-width: 1025px)",
tablet10Max: "(max-width: 1919px)",
tablet22Min: "(min-width: 1920px)",
landscape: "(orientation: landscape)",
portrait: "(orientation: portrait)",
}
function useMedia(
queries: string[],
values: ReactNode[],
defaultValue: ReactNode
): ReactNode {
const mediaQueryLists = useMemo(
() => queries.map(q => window.matchMedia(q)),
[queries.join(",")]
)
const memoValues = useMemo(() => values, [values.join(",")])
const getValue = useCallback(() => {
const index = mediaQueryLists.findIndex(m => m.matches)
return typeof memoValues[index] !== "undefined"
? memoValues[index]
: defaultValue
}, [defaultValue, mediaQueryLists, memoValues])
const [value, setValue] = useState(getValue)
useEffect(() => {
function handler(): void {
setValue(getValue)
}
mediaQueryLists.forEach(m => m.addListener(handler))
return () => mediaQueryLists.forEach(m => m.removeListener(handler))
}, [getValue, mediaQueryLists])
return value
}
export default useMedia
Example usage:
import React from "react"
import useMedia, { media } from "@ifit/hooks/useMedia"
const FontSizer = () => {
const size = useMedia(
[media.phoneMax, media.tablet10Min],
["10px", "20px"],
"14px"
)
return <span style={{ fontSize: size }}>Some Text</span>
}