From 662ad1bc09ac82c9bdf40a5a99e82ef7ef1a15bd Mon Sep 17 00:00:00 2001 From: Shinpei Date: Wed, 22 Apr 2020 00:03:56 +0900 Subject: [PATCH 1/4] Simplify --- src/hooks/useMediaQuery/index.ts | 36 ++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/hooks/useMediaQuery/index.ts b/src/hooks/useMediaQuery/index.ts index 0f3c20b..69b7ef7 100644 --- a/src/hooks/useMediaQuery/index.ts +++ b/src/hooks/useMediaQuery/index.ts @@ -1,8 +1,11 @@ import React, { useEffect, useMemo, useState, useCallback, useRef } from "react"; + interface IResponsibleHookConfig { [type: string]: string; } +type Order = "ASC" | "DESC"; + function checkBrowser() { if (typeof window !== undefined) { return true; @@ -19,30 +22,29 @@ function checkPC() { } } -function checkConfig(config: any) { +function checkConfig(config: IResponsibleHookConfig) { if (!config) { throw new Error("Need to config"); } } -function sortConfigWithSize(config: IResponsibleHookConfig, order: "ASC" | "DESC" = "ASC") { - const sortedConfig = {}; +function sortConfigWithSize(config: IResponsibleHookConfig, order: Order = "ASC") { const configEntries = Object.entries(config); - const sortedConfigEntries = configEntries.sort((before, after) => { + configEntries.sort((before, after) => { const beforeSize = Number(before[1].replace("px", "")); const afterSize = Number(after[1].replace("px", "")); - if (!before || !afterSize) { + if (!beforeSize || !afterSize || Number.isNaN(beforeSize) || Number.isNaN(afterSize)) { throw new Error("You need to use px in size"); } - return order === "ASC" ? beforeSize - afterSize : afterSize - beforeSize; + if (order === "ASC") + return beforeSize - afterSize; + return afterSize - beforeSize; }); - sortedConfigEntries.forEach(item => { - Object.assign(sortedConfig, { [item[0]]: item[1] }); - }); - return sortedConfig; + + return Object.fromEntries(sortConfig); } -export const useMediaQuery = (config: IResponsibleHookConfig, initial: string): [string, any?] => { +export const useMediaQuery = (config: IResponsibleHookConfig = {}, initial: string): [string, any?] => { try { if (!checkBrowser()) { throw new Error("It is not broswer environment, you need to use this in browser environment"); @@ -50,8 +52,6 @@ export const useMediaQuery = (config: IResponsibleHookConfig, initial: string): const [mediaType, setMediaType] = useState(""); const latestType = useRef(""); - checkConfig(config); - const sortedConfig = useMemo(() => sortConfigWithSize(config, "DESC"), [config]); const configKeys = useMemo(() => Object.keys(sortedConfig), [sortedConfig]); @@ -63,9 +63,8 @@ export const useMediaQuery = (config: IResponsibleHookConfig, initial: string): return type; }); } else { - const index = configKeys.findIndex(value => value === type); - if (index && index - 1 >= 0) { - setMediaType(configKeys[index - 1]); + if (configKeys.includes(type)) { + setMediaType(type); } else { setMediaType(initial); } @@ -113,6 +112,11 @@ export const useMediaQuery = (config: IResponsibleHookConfig, initial: string): }; } }, [mediaQuerys]); + + useEffect(() => { + checkConfig(config); + }, [config]); + return [mediaType]; } catch (error) { return ["Error", error]; From a96ce82693401a55b97689fa60ad05184dc91687 Mon Sep 17 00:00:00 2001 From: Shinpei Date: Wed, 22 Apr 2020 00:04:36 +0900 Subject: [PATCH 2/4] Update index.ts --- src/hooks/useMediaQuery/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks/useMediaQuery/index.ts b/src/hooks/useMediaQuery/index.ts index 69b7ef7..d6fc599 100644 --- a/src/hooks/useMediaQuery/index.ts +++ b/src/hooks/useMediaQuery/index.ts @@ -41,7 +41,7 @@ function sortConfigWithSize(config: IResponsibleHookConfig, order: Order = "ASC" return afterSize - beforeSize; }); - return Object.fromEntries(sortConfig); + return Object.fromEntries(configEntries); } export const useMediaQuery = (config: IResponsibleHookConfig = {}, initial: string): [string, any?] => { From ed68a33743b0c9235fec5ca3dfbe214e352425b2 Mon Sep 17 00:00:00 2001 From: Shinpei Date: Wed, 22 Apr 2020 00:05:53 +0900 Subject: [PATCH 3/4] Update index.ts --- src/hooks/useMediaQuery/index.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hooks/useMediaQuery/index.ts b/src/hooks/useMediaQuery/index.ts index d6fc599..81b4d47 100644 --- a/src/hooks/useMediaQuery/index.ts +++ b/src/hooks/useMediaQuery/index.ts @@ -63,8 +63,9 @@ export const useMediaQuery = (config: IResponsibleHookConfig = {}, initial: stri return type; }); } else { - if (configKeys.includes(type)) { - setMediaType(type); + const index = configKeys.findIndex(value => value === type); + if (index - 1 >= 0) { + setMediaType(configKeys[index - 1]); } else { setMediaType(initial); } From 0589bbc4cbaa5765695003daa4109c0326e1632a Mon Sep 17 00:00:00 2001 From: Shinpei Date: Wed, 22 Apr 2020 00:17:52 +0900 Subject: [PATCH 4/4] Update index.ts --- src/hooks/useMediaQuery/index.ts | 207 +++++++++++++++---------------- 1 file changed, 101 insertions(+), 106 deletions(-) diff --git a/src/hooks/useMediaQuery/index.ts b/src/hooks/useMediaQuery/index.ts index 81b4d47..f97d50e 100644 --- a/src/hooks/useMediaQuery/index.ts +++ b/src/hooks/useMediaQuery/index.ts @@ -1,127 +1,122 @@ -import React, { useEffect, useMemo, useState, useCallback, useRef } from "react"; +import React, { useEffect, useMemo, useState, useCallback, useRef } from 'react'; interface IResponsibleHookConfig { - [type: string]: string; + [type: string]: string; } -type Order = "ASC" | "DESC"; +type Order = 'ASC' | 'DESC'; function checkBrowser() { - if (typeof window !== undefined) { - return true; - } - return false; + return typeof window !== undefined; } function checkPC() { - const PC_OS = "win16|win32|win64|mac|macintel"; - if (navigator.platform && PC_OS.indexOf(navigator.platform.toLowerCase()) >= 0) { - return true; - } else { - return false; - } + const PC_OS = 'win16|win32|win64|mac|macintel'; + return !!(navigator.platform && PC_OS.indexOf(navigator.platform.toLowerCase()) >= 0); } function checkConfig(config: IResponsibleHookConfig) { - if (!config) { - throw new Error("Need to config"); - } + if (!config) { + throw new Error('Need to config'); + } } -function sortConfigWithSize(config: IResponsibleHookConfig, order: Order = "ASC") { - const configEntries = Object.entries(config); - configEntries.sort((before, after) => { - const beforeSize = Number(before[1].replace("px", "")); - const afterSize = Number(after[1].replace("px", "")); - if (!beforeSize || !afterSize || Number.isNaN(beforeSize) || Number.isNaN(afterSize)) { - throw new Error("You need to use px in size"); - } - if (order === "ASC") - return beforeSize - afterSize; - return afterSize - beforeSize; - }); +function sortConfigWithSize(config: IResponsibleHookConfig, order: Order = 'ASC') { + const configEntries = Object.entries(config); + configEntries.sort((before, after) => { + const beforeSize = Number(before[1].replace('px', '')); + const afterSize = Number(after[1].replace('px', '')); + if (!beforeSize || !afterSize || Number.isNaN(beforeSize) || Number.isNaN(afterSize)) { + throw new Error('You need to use px in size'); + } + if (order === 'ASC') return beforeSize - afterSize; + return afterSize - beforeSize; + }); - return Object.fromEntries(configEntries); + return Object.fromEntries(configEntries); } -export const useMediaQuery = (config: IResponsibleHookConfig = {}, initial: string): [string, any?] => { - try { - if (!checkBrowser()) { - throw new Error("It is not broswer environment, you need to use this in browser environment"); - } - const [mediaType, setMediaType] = useState(""); - const latestType = useRef(""); - - const sortedConfig = useMemo(() => sortConfigWithSize(config, "DESC"), [config]); - const configKeys = useMemo(() => Object.keys(sortedConfig), [sortedConfig]); - - const eventHandlerGenerator = useCallback( - (type: string) => (event: MediaQueryListEvent) => { - if (event.matches) { - setMediaType(prev => { - latestType.current = prev; - return type; - }); - } else { - const index = configKeys.findIndex(value => value === type); - if (index - 1 >= 0) { - setMediaType(configKeys[index - 1]); - } else { - setMediaType(initial); - } - } - }, - [initial, configKeys] - ); - - const mediaQuerys = useMemo( - () => - configKeys.map(key => { - const mediaQuery = window.matchMedia(`screen and (max-width: ${config[key]})`); - return { mediaQuery, eventHandler: eventHandlerGenerator(key), type: key }; - }), - [configKeys] - ); - - useEffect(() => { - const shouldInitial = !mediaQuerys.reverse().some(item => { - const { mediaQuery, type } = item; - if (mediaQuery.matches) { - setMediaType(type); - latestType.current = type; - return true; - } - return false; - }); - if (shouldInitial) { - setMediaType(initial); - } - }, [mediaQuerys, initial]); - - useEffect(() => { - if (checkPC()) { - mediaQuerys.forEach(item => { - const { mediaQuery, eventHandler } = item; - mediaQuery.addEventListener("change", eventHandler); - }); - - return () => { - mediaQuerys.forEach(item => { - const { mediaQuery, eventHandler } = item; - mediaQuery.removeEventListener("change", eventHandler); - }); - }; - } - }, [mediaQuerys]); - - useEffect(() => { - checkConfig(config); - }, [config]); - - return [mediaType]; - } catch (error) { - return ["Error", error]; +export const useMediaQuery = ( + config: IResponsibleHookConfig = {}, + initial: string +): [string, any?] => { + try { + if (!checkBrowser()) { + throw new Error('It is not broswer environment, you need to use this in browser environment'); } + const [mediaType, setMediaType] = useState(''); + const latestType = useRef(''); + + const sortedConfig = useMemo(() => sortConfigWithSize(config, 'DESC'), [config]); + const configKeys = useMemo(() => Object.keys(sortedConfig), [sortedConfig]); + + const eventHandlerGenerator = useCallback( + (type: string) => (event: MediaQueryListEvent) => { + if (event.matches) { + setMediaType(prev => { + latestType.current = prev; + return type; + }); + } else { + const index = configKeys.findIndex(value => value === type); + if (index - 1 >= 0) { + setMediaType(configKeys[index - 1]); + } else { + setMediaType(initial); + } + } + }, + [initial, configKeys] + ); + + const mediaQuerys = useMemo( + () => + configKeys.map(key => { + const mediaQuery = window.matchMedia(`screen and (max-width: ${config[key]})`); + return { mediaQuery, eventHandler: eventHandlerGenerator(key), type: key }; + }), + [configKeys] + ); + + useEffect(() => { + const shouldInitial = !mediaQuerys.reverse().some(item => { + const { mediaQuery, type } = item; + if (mediaQuery.matches) { + setMediaType(type); + latestType.current = type; + return true; + } + return false; + }); + if (shouldInitial) { + setMediaType(initial); + } + }, [mediaQuerys, initial]); + + useEffect(() => { + if (checkPC()) { + mediaQuerys.forEach(item => { + const { mediaQuery, eventHandler } = item; + mediaQuery.addEventListener('change', eventHandler); + }); + + return () => { + mediaQuerys.forEach(item => { + const { mediaQuery, eventHandler } = item; + mediaQuery.removeEventListener('change', eventHandler); + }); + }; + } + }, [mediaQuerys]); + + useEffect(() => { + checkConfig(config); + }, [config]); + + return [mediaType]; + } catch (error) { + return ['Error', error]; + } }; export default useMediaQuery;