gymnastjs/gymnast

View on GitHub
src/useResolution/index.tsx

Summary

Maintainability
A
1 hr
Test Coverage
import * as React from 'react'
import {
DisplayAliases,
GridProps,
OneResolutionGrid,
GymnastContextType,
} from '../types'
import log from '../log'
import { getValue } from '../utils'
import { errors } from '../errors'
import { register, unregister, supportsMatchMedia } from './mediaQuery'
import Context from '../gymnastProvider/context'
import {
checkShouldShow,
getMediaQueries,
getSingleResolutionProps,
hasTrueValues,
isObject,
ShouldShow,
} from './useResolution.logic'
 
function anyPropsUseResolutionFormat(
resolutionKeys: string[],
props: { [key: string]: any }
) {
return resolutionKeys.some(key => {
const { [key]: prop } = props
 
return isObject(prop)
})
}
 
type MediaProps = {
show: string | string[] | undefined
resolutionKeys: string[]
context: GymnastContextType
props: {}
}
 
function getQueries({ show, resolutionKeys, context, props }: MediaProps) {
const displayAliases: DisplayAliases = getValue(context, 'displayAliases')
let queries = show
 
if (!show && anyPropsUseResolutionFormat(resolutionKeys, props)) {
queries = Object.keys(displayAliases)
}
 
return getMediaQueries(queries, displayAliases)
}
 
function useMedia(props: MediaProps) {
const queries = getQueries(props)
const initialState = checkShouldShow(queries)
const [shouldShow, setShouldShow] = React.useState<ShouldShow | undefined>(
initialState
)
 
function onMediaQueryChange(mq: any = {}, alias: string) {
if (shouldShow && shouldShow[alias] !== mq.matches) {
setShouldShow({
...shouldShow,
[alias]: mq.matches,
})
}
}
 
React.useEffect(() => {
Object.keys(queries).forEach(alias => {
register(queries[alias], alias, onMediaQueryChange)
})
 
return () =>
Object.keys(queries).forEach(alias => {
unregister(queries[alias], onMediaQueryChange)
})
}, [...Object.values(shouldShow || {}), props.show])
 
return shouldShow
}
 
Function `useResolution` has 37 lines of code (exceeds 25 allowed). Consider refactoring.
export default function useResolution<A extends GridProps>(
resolutionKeys: Array<string>,
props: A,
allowMatchMedia: boolean = supportsMatchMedia
): [boolean, A & OneResolutionGrid] {
if (!allowMatchMedia) {
log.warn(errors.NOMATCHMEDIA)
return [
true,
getSingleResolutionProps({
props,
shouldShow: undefined,
resolutionKeys: [],
}),
]
}
const context = React.useContext(Context)
 
const { show, ...restProps } = props
const shouldShow = useMedia({
show,
resolutionKeys,
context,
props: restProps,
})
 
if (show && shouldShow && !hasTrueValues(shouldShow)) {
return [
false,
getSingleResolutionProps({
props,
shouldShow: undefined,
resolutionKeys: [],
}),
]
}
 
return [
true,
getSingleResolutionProps({
props,
shouldShow,
resolutionKeys,
}),
]
}