Reace Hooks その⑦ 発展編(任意)

Next.js-2.React Hooks編-

これまで、React HooksのuseState,useEffect,useRefについて学んできました。

ここからは発展編ということで、必須ではありませんが、知っておくと便利なHooks(useContext,useReducer)について触れていきます。

💡useContextとは?

useContextは、「親コンポーネントから子コンポーネントにデータを渡すのをラクにする仕組み」 です。

普通、データを渡すには props を使いますが、階層が深くなるとめちゃくちゃ面倒になります

💩 「props 地獄」を解決するのが useContext

useContextの使い方

実際にコードを書いて動きを見ていきましょう。

まずアプリを作成します。

npx create-next-app@latest use-context-app

次に、useContextを定義するファイルを作成します。

app/UserContext.js

import { createContext } from "react";

// ✅ ユーザー情報を管理する Context を作成
export const UserContext = createContext();

そして、孫、子、親コンポーネントを作成していきます。

app/components/GrandChild.js

"use client";

import { useContext } from "react";
import { UserContext } from "../UserContext";

function GrandChild() {
    const { user } = useContext(UserContext); // ✅ Context からユーザー情報を取得

    return (
        <div style={{ border: "2px solid blue", padding: "10px", marginTop: "10px" }}>
            <h3>👶 孫コンポーネント</h3>
            <p><strong>ユーザー名:</strong> {user.name}</p>
            <p><strong>メールアドレス:</strong> {user.email}</p>
        </div>
    );
}

export default GrandChild;

app/components/Child.js

"use client";

import { useContext } from "react";
import { UserContext } from "../UserContext"; // ✅ Context をインポート
import GrandChild from "./GrandChild"; // ✅ 孫コンポーネントをインポート

function Child() {
    const { user } = useContext(UserContext); // ✅ Context からユーザー情報を取得

    return (
        <div style={{ border: "2px solid green", padding: "10px" }}>
            <h2>👦 子コンポーネント</h2>
            <p><strong>ユーザー名:</strong> {user.name}</p>
            <p><strong>メールアドレス:</strong> {user.email}</p>
            <GrandChild /> {/* ✅ 孫コンポーネントを表示 */}
        </div>
    );
}

export default Child;

app/components/App.js

"use client";

import { useState } from "react";
import { UserContext } from "../UserContext"; // ✅ Context をインポート
import Child from "./Child"; // ✅ 子コンポーネントをインポート

function App() {
    const [user, setUser] = useState({
        name: "しょんべん太郎",
        email: "shonben@example.com",
    });

    return (
        // ✅ `UserContext.Provider` で `user` を全コンポーネントに提供
        <UserContext.Provider value={{ user, setUser }}>
            <div style={{ border: "2px solid red", padding: "10px" }}>
                <h1>👨‍💻 親コンポーネント(App)</h1>
                <p><strong>ユーザー名:</strong> {user.name}</p>
                <p><strong>メールアドレス:</strong> {user.email}</p>
                <Child />
            </div>
        </UserContext.Provider>
    );
}

export default App;

最後にpage.jsで読み込みます。

app/page.js

import Image from "next/image";

import App from "./components/App";

export default function Home() {
  return (
    <App />
  );
}

開発サーバーを立ち上げて画面を確認します。

npm run dev

このように親コンポーネントで定義した値をそれぞれのコンポーネントで継承し表示しています。

コード解説

まずUserContext.jsですが、

app/UserContext.js

export const UserContext = createContext();

このようにUserContextというContextを作成しています。

またexportの後に「default」をつけていませんが、コンポーネントなどの関数の宣言(function)」は export default でエクスポートできますが、今回のように定数の宣言の場合は「default」がつけられません

次に、親コンポーネントの主要な部分を説明します。

app/components/App.js

import { UserContext } from "../UserContext"; // ✅ Context をインポート

UserContext.jsからUserConxetをインポートしています。

このように、「default」をつけずにエクスポートされたものは{}をつけて且つエクスポート元で定義した名前をそのまま記述する必要があります。

逆に、「default」をつけたエクスポートした関数はインポート先では別の名前でインポートすることもできます。

<UserContext.Provider value={{ user, setUser }}>

親コンポーネントではこのように渡したい値を「Provider」と呼ばれるコンポーネントのvalueプロパティに設定します。

valueの値が{{}}と二重括弧になっていますが、内側の{}はuser、setUserと複数の値を渡すためにオブジェクトとして渡すための{}です。

渡す値が1つの場合は{}は1重で大丈夫です。

次に子コンポーネントを見ます。

app/components/Child.js

import { UserContext } from "../UserContext"; 

子コンポーネントでもUserContext.jsからUserContextをインポートします。

 const { user } = useContext(UserContext);

ここで親コンポーネントで設定された値をuseContextを使って受取り、{user}オブジェクトに代入しています。

ここでも、渡ってくる値が1つの場合は、{}をつけてオブジェクトにする必要はありません。

 <p><strong>ユーザー名:</strong> {user.name}</p>
 <p><strong>メールアドレス:</strong> {user.email}</p>

ここで親コンポーネントで定義したuserオブジェクトの値をそれぞれ表示しています。

userオブジェクト(app/components/App.js)

{
   name: "しょんべん太郎",
   email: "shonben@example.com",
 }

最後に孫コンポーネントを見ていきます。

app/components/GrandChild.js

import { UserContext } from "../UserContext";
const { user } = useContext(UserContext);
 <p><strong>ユーザー名:</strong> {user.name}</p>
 <p><strong>メールアドレス:</strong> {user.email}</p>

このように、孫コンポーネントと子コンポーネントが全く同じ書き方になっています。

useContextでどこからでもデータにアクセスできる

propsでのデータ継承のように、親→子→孫とバケツリレーをしなくても、例えば子コンポーネントでは継承せずに、孫コンポーネントのみでも扱えたりします。

つまり、useContextを使うことで、

親コンポーネントで渡したデータにどこからでもアクセスできる

というわけです。

なので、子コンポーネントと孫コンポーネントで同じ書き方でも継承できたのです。

useContextを使うケース

ここで見てきたユーザー情報=ログイン情報ようなグローバルで扱いたいデータ向けに使用します。

コメント

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