프로토타입 모음기: 전역 상태 이용한 폰트 세팅 변경(Zustand + Tailwind CSS)

Gaebalgom·2025년 3월 31일
0

만든 것

  • Zustand를 이용한 상태 공유를 이용해서 tailwind 를 이용해 다른 컴포넌트의 폰트 세팅을 바꿔보자.

🚀 목표

  • Zustand 사용에 조금 더 익숙해져보기
  • tailwind font 세팅에 익숙해져 보기

소스코드

tailwind

먼저 사용할 폰트를 지정해 둡시다. 각 폰트별로 다른 이름이나 변수를 사용할 수도 있지만, 기본 설정을 변경할 수도 있습니다.

@import url("https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/static/pretendard-dynamic-subset.min.css");
@import url("https://fonts.googleapis.com/css2?family=Noto+Serif+KR:wght@200..900&display=swap");
@import "tailwindcss";

@theme {
  --font-sans: "Pretendard", sans;
  --font-serif: "Noto Serif KR", serif;
}

Zustand

import { create } from "zustand";
import { devtools, persist } from "zustand/middleware";

interface FontState {
  font: "font-sans" | "font-serif" | "font-mono";
  change: (font: "font-sans" | "font-serif" | "font-mono") => void;
}

export const useFontStore = create<FontState>()(
  devtools(
    persist(
      (set): FontState => ({
        font: "font-mono",
        change: (font) => set({ font }),
      }),
      {
        name: "fontStore",
      }
    )
  )

tailwind 유틸리티 클래스를 적용할 스토어랑 이를 바꾸는 액션을 만들어줍니다. 또한 새로고침을 해도 해제가 안되도록 fontStore를 적용시켜 줍시다.

React

import "./App.css";
import FontSelector from "./FontSelector";
import { useFontStore } from "./zustand/font";

function App() {
  const font = useFontStore((state) => state.font);

  return (
    <>
      <h1 className={font}>Vite + React</h1>
      <div className={`card ${font}`}>
        <p>
          Edit <code>src/App.tsx</code> and save to test HMR
        </p>
        <p>Click on the Vite and React logos to learn more</p>
      </div>
      <FontSelector />
    </>
  );
}

export default App;

```tsx
import { useId } from "react";
import { useFontStore } from "./zustand/font";

const FontSelector = () => {
  const id = useId();
  // 접근성을 위해 label의 htmlFor, select의 id 같은 옵션을 챙겨줍시다.
  const change = useFontStore((state) => state.change);
  const font = useFontStore((state) => state.font);
  type ChangeFunc = typeof change;
  type FontType = Parameters<ChangeFunc>[0];

  const handleChange: React.ChangeEventHandler<HTMLSelectElement> = (e) => {
    change(e.target.value as FontType);
  };

  return (
    <>
      <label htmlFor={id}>Choose Font:</label>
      <select onChange={handleChange} id={id} value={font}>
        <option value="font-serif">Serif</option>
        <option value="font-mono">Mono</option>
        <option value="font-sans">Sans Serif</option>
      </select>
    </>
  );
};

export default FontSelector;

주의점

  • 유틸리티 클래스의 이름만 일부분 State를 통해서 바꿨을 때, 제대로 적용이 안되는 이슈가 있었습니다. 유틸리티 클래스 전체를 바꿔주니 해결되었습니다.
  • create()() 형태를 Zustand는 사용합니다. 자세한 설명은 typescript 가이드 를 참고해주세요.
  • id를 고정된 값으로 사용하다간 여러 컴포넌트 사용시 id값이 충돌날 수 있습니다. 이를 막기 위해 useId 훅을 사용합시다.
profile
하루 하루 개발하고 있는 취준생입니다.

0개의 댓글