React で Cookie 処理を行う

Typescript

React で Cookie 処理を行う

react で cookie 処理をする場合、他のコンポーネントでの cookie 更新によるリレンダリング処理などが手間になることがありますが、react-cookieを使うことで cookie 情報を state として管理出来るため、かなり開発が楽になります。

開発環境

OS Name: Microsoft Windows 11 Home
OS Version: 10.0.22621 N/A Build 22621
CPU: 12th Gen Intel(R) Core(TM) i7-12700K 3.60 GHz
node --version
>>> v16.16.0
npm --version
>>> 8.11.0

使用したreact-cookieのバージョンは7.0.2になります

react-cookie の install

react で cookie を用いる場合は、cookie を state として管理してくれるこちらのライブラリを使うのがおススメです。
react-cookie

npm i react-cookie

でインストールできます。

基本的な使い方

Provider の設定

cookie を state 管理したい範囲をCookiesProviderで包みます。redux や recoil、context と同じノリです。素朴には root 付近になると思います

import { CookiesProvider } from "react-cookie";

const root = ReactDOM.createRoot(
  document.getElementById("root") as HTMLElement
);

root.render(
  <React.StrictMode>
      <CookiesProvider defaultSetOptions={{ path: "/" }}>
            <SomeApp />
      </CookiesProvider>
    </RecoilRoot>
  </React.StrictMode>
);

この時CookiesProviderに渡すdefaultSetOptionは以下のような一般的な Cookie のオプションのようです。便利ですね

export interface CookieSetOptions {
  path?: string;
  expires?: Date;
  maxAge?: number;
  domain?: string;
  secure?: boolean;
  httpOnly?: boolean;
  sameSite?: boolean | "none" | "lax" | "strict";
  partitioned?: boolean;
}

cookie のオプション詳細はmdn web docsをご参照ください

useCookie で cookie を取得する

CookiesProvider以下の component について、useCookieを用いて cookie を取得することができます。

import { useCookies } from "react-cookie";

const SomeComponent = () => {
  const [cookies, setCookie, removeCookie, updateCookies] = useCookies([]);

  return <div>{JSON.stringify(cookies)}</div>;
};

useCookiesに渡すdependencies引数は react の state 更新をその cookie 更新時のみに絞ることができます。

import { useCookies } from "react-cookie";

const SomeComponent = () => {
  // cookieのuserNameが更新された時のみcookies stateが更新されます
  const [cookies, setCookie, removeCookie, updateCookies] = useCookies([
    "userName",
  ]);

  return <div>{JSON.stringify(cookies)}</div>;
};

cookie を update したい場合は、第二返り値のsetCookieを用います

import { useCookies } from "react-cookie";

const SomeComponent = () => {
  const [cookies, setCookie, removeCookie, updateCookies] = useCookies([
    "userName",
  ]);

  return (
    <button
      onClick={() => {
        setCookie("userName", "sato");
      }}
    >
      update cookie
    </button>
  );
};

TypeScript での使い方

TypeScript でreact-cookieを用いている場合は、ジェネリック型を使ってある程度の型情報を与えることができます。
useCookie のジェネリックは以下のようになっています。

import { Cookie, CookieSetOptions } from "universal-cookie";
export default function useCookies<
  T extends string,
  U = {
    [K in T]?: any;
  }
>(
  dependencies?: T[]
): [
  U,
  (name: T, value: Cookie, options?: CookieSetOptions) => void,
  (name: T, options?: CookieSetOptions) => void,
  () => void
];

T が cookie の key に関する型情報、U が得られる cookie の型情報になっています

key に型情報を与える

従って、T にリテラルを与えることで cookie の key についてフリーテキストでの入力を避けられるようになります。

import { useCookies } from "react-cookie";

type CookieKey = "userName" | "age";

const SomeComponent = () => {
  const [cookies, setCookie, removeCookie, updateCookies] =
    useCookies<CookieKey>(["userName"]);

  return (
    <button
      onClick={() => {
        setCookie("userName", "tanaka");
      }}
    >
      update cookie
    </button>
  );
};

cookie の辞書に型情報を与える

useCookiesのジェネリックの第二引数に cookie のオブジェクトの型情報を渡すことで、cookie についても型を与えることができます。

import { useCookies } from "react-cookie";

type CookieKey = "userName" | "age" | "family";
type UserCookie = {
  userName?: string;
  age?: number;
  family?: {
    father: string;
    mother: string;
  };
};

const SomeComponent = () => {
  const [cookies, setCookie, removeCookie, updateCookies] = useCookies<
    CookieKey,
    UserCookie
  >([]);

  // 型補完が利くようになる
  console.log(cookies.family?.father);
  console.log(cookies.family?.mother);
  console.log(cookies.userName);

  return (
    <button
      onClick={() => {
        setCookie("userName", "suzuki");
      }}
    >
      update cookie
    </button>
  );
};

初期化するまでは undefined で返ってくるので、基本的に nullable 推奨です

また、setCookie については型の補完が利かないため、どうしても型を加えたい場合は自分でカスタムフックを定義することになります。

import { useCookies } from "react-cookie";
import { CookieSetOptions } from "universal-cookie";

type CookieKey = "userName" | "age" | "family";
type UserCookie = {
  userName?: string;
  age?: number;
  family?: {
    father: string;
    mother: string;
  };
};

export const useUserCookie = (): [
  UserCookie,
  (value: UserCookie["userName"], options?: CookieSetOptions) => void,
  (value: UserCookie["age"], options?: CookieSetOptions) => void,
  (value: UserCookie["family"], options?: CookieSetOptions) => void
] => {
  const [cookies, setCookie, removeCookie, updateCookies] = useCookies<
    CookieKey,
    UserCookie
  >(["age", "family", "userName"]);

  const setUserNameCookie = useCallback(
    (value: UserCookie["userName"], options?: CookieSetOptions) => {
      setCookie("userName", value, options);
    },
    []
  );

  const setUserAgeCookie = useCallback(
    (value: UserCookie["age"], options?: CookieSetOptions) => {
      setCookie("age", value, options);
    },
    []
  );

  const setFamilyCookie = useCallback(
    (value: UserCookie["family"], options?: CookieSetOptions) => {
      setCookie("family", value, options);
    },
    []
  );

  return [cookies, setUserNameCookie, setUserAgeCookie, setFamilyCookie];
};

コメント

タイトルとURLをコピーしました