Open1
宣言的にブレイクポイント検出を行いたい
型情報はもっと上手に扱えるはず。
type UseEffectTarget = {
[key: string]: string | number | boolean;
};
type Queries = {
[key: string]: MediaQueryList;
};
const effectWatcher = (
target: UseEffectTarget,
props: string,
callback: () => void,
) => {
let value = target[props];
Object.defineProperty(target, props, {
get: () => value,
set: (newValue) => {
value = newValue;
callback();
},
configurable: true,
});
};
const useEffect = (callback: () => void, target: UseEffectTarget) => {
Object.entries(target).forEach((current) => {
const [prop] = [...current];
effectWatcher(target, prop, callback);
});
};
const createQueryStats = (queries: Queries): UseEffectTarget => {
return Object.entries(queries).reduce((prev, current) => {
const [size, query] = [...current];
return {
...prev,
[size]: query.matches,
};
}, {});
};
const setMediaOnchangeEvents = (
queries: Queries,
queryStats: UseEffectTarget,
) => {
Object.entries(queries).forEach((current) => {
const [size, query] = [...current];
query.onchange = (event) => {
queryStats[size] = event.matches;
};
});
};
const showCurrentBreakpoint = (queries: UseEffectTarget) => {
queries.lg
? console.log('lg layout')
: queries.md
? console.log('md layout')
: console.log('sm layout');
};
const main = () => {
const queries: Queries = {
lg: window.matchMedia('(min-width: 1024px)'),
md: window.matchMedia('(min-width: 768px)'),
sm: window.matchMedia('(min-width: 0px)'),
};
const queryStats: UseEffectTarget = createQueryStats(queries);
// 初回実行時
setMediaOnchangeEvents(queries, queryStats);
showCurrentBreakpoint(queryStats);
// Breakpoint が変更された場合に実行
useEffect(() => {
showCurrentBreakpoint(queryStats);
}, queryStats);
};
main();