案件でNext.jsを触る機会がありました。
コンポーネント間で共通して使用できる値を作りたかったのですが、中々手こずったのでこちらの記事でご紹介します。
やりたかったこと
イメージは、以下の通りです。
・コンポーネントAで、isActiveという変数を変更(例) false <=> true
・コンポーネントBは、値を変更しないでisActiveの真偽値によって表示・非表示
実装方法について
ご紹介するのはミニマムな実装方法になります。
公開されているパッケージなどを使う方法もありますが、今回はuseContextを使うやり方にしています。
01.State専用ファイル作成
まずは、State用のファイルを作成します。
//app/_state/isActiveState.js
import React, { useState } from "react";
export const IsActiveContext = React.createContext({
isActive: false,
setIsActive: () => void false,
});
export const MainProvider = ({ children }) => {
const [isActive, setIsActive] = useState(false);
return <IsActiveContext.Provider value={{ isActive, setIsActive }}>{children}</IsActiveContext.Provider>;
};
02.ルートファイルに追記
page.tsxにState専用ファイルをインポートして、その中のProviderで子コンポーネントを挟んであげないといけません。
これをしないと、グロールな値が更新できない(?)ようです。
ここに辿り着くまでに時間がかかりました、、
//app/about/page.tsx
"use client";
import { MainProvider } from "@/app/_state/IsActiveState";
import ComponentA from "@/app/_component/layout/componentA";
import ComponentB from "@/app/_component/layout/componentB";
export default function About() {
return (
<MainProvider>
<ComponentA />
<ComponentB />
</MainProvider>
);
}
03.コンポーネントAに追記
このファイル内で、isActiveの真偽値を変更していきます。
useContextで、State専用ファイル内にあるIsActiveContextを使用します。
onClickイベントで、isActiveの値を変更しています。
//app/_component/layout/componentA.tsx
"use client";
import React, { useContext, useState } from "react";
import Link from "next/link";
import { IsActiveContext } from "@/app/_state/IsActiveState";
import style from "@/app/_styles/layout/componentA.module.scss";
export default function ComponentA() {
const { isActive, setIsActive } = useContext(IsActiveContext);
const toggleActive = () => {
setIsActive(!isActive);
};
return (
<header className={style.body}>
<button className={`${style.button} ${isActive ? style["is-active"] : ""}`} onClick={toggleActive}>
<span></span>
<span></span>
<span></span>
</button>
</header>
);
}
04.コンポーネントBに追記
こちらのコンポーネントBでは、値の変更はしないのでisActiveのみを使用します。
"use client";
import React, { useContext, useState } from "react";
import Link from "next/link";
import { IsActiveContext } from "@/app/_state/IsActiveState";
import style from "@/app/_styles/layout/componentB.module.scss";
export default function ComponentB() {
const { isActive } = useContext(IsActiveContext);
return (
<>
<div className={`${style.body} ${isActive ? style["is-open"] : ""}`}>
</div>
</>
);
}
一旦グローバルステート設定が完了して、実際に動作が確認できました。
今回のポイントは、Providerをルートファイルに読み込み要素を挟んであげる事だったと思います。
まとめ
今回は、Next.jsを使ったコンポーネント間で使用できる値を作成・使用する方法についてでした。
グローバルな値は個人的に結構設定して使うことがあるので、非常に勉強になりました。
ぜひ参考にしてみてください。
最後までご閲覧いただき、ありがとうございました!