react useSyncExternalStore를 사용하여 useMediaQuery 만들기
사용법
const StatusBar = () => {
const isDark = useMediaQuery('(prefers-color-scheme: dark)')
return (<div>{isDark ? 'Dark Mode' : 'Light Mode'}</div>)
}
구현
// useMediaQuery.js
import { useSyncExternalStore } from "react";
export function useMediaQuery(query) {
const matches = useSyncExternalStore(
(callback) => subscribe(query, callback),
() => getSnapshot(query),
getServerSnapshot
);
return matches;
}
function getSnapshot(query) {
return window.matchMedia(query).matches;
}
function subscribe(query, callback) {
const mql = window.matchMedia(query);
mql.addEventListener("change", callback);
return () => {
mql.removeEventListener("change", callback);
};
}
function getServerSnapshot() {
return false;
}
// useMediaQuery.ts
import { useSyncExternalStore } from 'react'
type Query = string
type CallBack = () => void
export default function useMediaQuery(query: Query) {
const matches = useSyncExternalStore(
(callback) => subscribe(query, callback),
() => getSnapshot(query),
getServerSnapshot
)
return matches
}
function getSnapshot(query: Query) {
return window.matchMedia(query).matches
}
function subscribe(query: Query, callback: CallBack) {
const mql = window.matchMedia(query)
mql.addEventListener('change', callback)
return () => {
mql.removeEventListener('change', callback)
}
}
function getServerSnapshot() {
return false
}