카테고리 없음

react useSyncExternalStore를 사용하여 useMediaQuery 만들기

Neda 2023. 11. 5. 04:22

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
}