React 自定义 useMediaQuery Hooks 媒体查询

37 min read

React 自定义 useMediaQuery Hooks 媒体查询

import { useState, useEffect } from "react";

const useMediaQuery = (query) => {
  const [matches, setMatches] = useState(false);

  useEffect(() => {
    const media = window.matchMedia(query);
    if (media.matches !== matches) {
      setMatches(media.matches);
    }
    const listener = () => setMatches(media.matches);
    window.addEventListener("resize", listener);
    return () => window.removeEventListener("resize", listener);
  }, [matches, query]);

  return matches;
}

export default useMediaQuery;

Window 的matchMedia() 方法返回一个新的MediaQueryList 对象,表示指定的媒体查询 (en-US)字符串解析后的结果。返回的MediaQueryList 可被用于判定Document是否匹配媒体查询,或者监控一个document 来判定它匹配了或者停止匹配了此媒体查询。

import React from "react";
import "./index.css";
import useMediaQuery from "./hooks/useMediaQuery";

function App() {
  // You can use any @media property
  const isDesktop = useMediaQuery('(min-width: 960px)');

  return (
    <div className="App">
      {isDesktop ? <h1>Desktop</h1> : <h1>Mobile</h1>}
      <Navbar isDesktop={isDesktop}/>
    </div>
  );
}

// Navbar component
const Navbar = ({isDesktop}) => (
  <nav className={`base ${isDesktop ? "desktop" : "mobile"}`}>
    <Icon />
    <Icon />
    <Icon />
    <Icon />
  </nav>
);


// SVG icon component
const Icon = () => (
  <svg viewBox="0 0 512 512">
    <path
      fill="currentColor"
      d="M448 96h-64l-64-64v134.4a96 96 0 0 0 192 0V32zm-72 80a16 16 0 1 1 16-16 16 16 0 0 1-16 16zm80 0a16 16 0 1 1 16-16 16 16 0 0 1-16 16zm-165.41 16a204.07 204.07 0 0 0-34.59 2.89V272l-43.15-64.73a183.93 183.93 0 0 0-44.37 26.17L192 304l-60.94-30.47L128 272v-80a96.1 96.1 0 0 0-96-96 32 32 0 0 0 0 64 32 32 0 0 1 32 32v256a64.06 64.06 0 0 0 64 64h176a16 16 0 0 0 16-16v-16a32 32 0 0 0-32-32h-32l128-96v144a16 16 0 0 0 16 16h32a16 16 0 0 0 16-16V289.86a126.78 126.78 0 0 1-32 4.54c-61.81 0-113.52-44.05-125.41-102.4z"
    />
    <path
      fill="currentColor"
      d="M376 144a16 16 0 1 0 16 16 16 16 0 0 0-16-16zm80 0a16 16 0 1 0 16 16 16 16 0 0 0-16-16zM131.06 273.53L192 304l-23.52-70.56a192.06 192.06 0 0 0-37.42 40.09zM256 272v-77.11a198.62 198.62 0 0 0-43.15 12.38z"
    />
  </svg>
);

export default App;