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];
};
コメント