【NextJS】Hooks-useContext

1. 概要

前回はHooksのuseState(値を共有)の使い方についてでした。今回はHooksのuseContextを使いコンポネント間で値を共有する内容となります。

対象としては開発を1年程やってて自分で最初から開発してみたい方になります。そのため細かい用語などの説明はしません。

2. nodeのインストール

こちらを参考

3. プロジェクトを作成

こちらを参考

4. 必要なライブラリをインストール

こちらを参考

5. ソースコード

※前回より差分のみを記載

5-1-1. src/app/hooks/hook03/page.module.scss

.component {
  color: blue;
  & ul {
    margin-left: 20px;
    & li {
      list-style: disc;
    }
  }
}

5-1-2. src/app/hooks/hook03/counter-provider.tsx

import { useState, createContext, Context, useContext } from "react";

const CounterWatchContext: Context<number> = createContext(0);
const CounterUpdateContext: Context<any> = createContext(0);

export const CounterProvider = ({ children }: any) => {
  const [count, setCount] = useState(0);
  return (
    <CounterWatchContext.Provider value={count}>
      <CounterUpdateContext.Provider value={setCount}>
        {children}
      </CounterUpdateContext.Provider>
    </CounterWatchContext.Provider>
  );
};

export const useWatchCounter = () => useContext(CounterWatchContext);
export const useUpdateCounter = () => useContext(CounterUpdateContext);

5-1-3. src/app/hooks/hook03/grandchild.tsx

import Box from "@mui/material/Box";
import { useWatchCounter } from "./counter-provider";

const Grandchild = () => {
  const count = useWatchCounter();
  return (
    <>
      <Box
        sx={{
          width: "100%",
          p: 2,
          border: "1px dashed grey",
          borderRadius: "20px",
          backgroundColor: "cyan",
          "&:hover": {
            backgroundColor: "white",
            opacity: [0.9, 0.8, 0.7],
          },
        }}
      >
        Grandchild({count})
      </Box>
    </>
  );
};

export default Grandchild;

5-1-4. src/app/hooks/hook03/child.tsx

import Box from "@mui/material/Box";
import Grandchild from "./grandchild";
import { useWatchCounter } from "./counter-provider";

const Child = () => {
  const count = useWatchCounter();
  return (
    <>
      <Box
        sx={{
          width: "100%",
          p: 2,
          border: "1px dashed grey",
          borderRadius: "20px",
          backgroundColor: "yellow",
          "&:hover": {
            backgroundColor: "white",
            opacity: [0.9, 0.8, 0.7],
          },
        }}
      >
        Child({count})
        <Grandchild />
      </Box>
    </>
  );
};

export default Child;

5-1-5. src/app/hooks/hook03/myself.tsx

import { Button } from "@mui/material";
import Box from "@mui/material/Box";
import scss from "./page.module.scss";
import GoBack from "@/lib/components/go-back";
import { useWatchCounter, useUpdateCounter } from "./counter-provider";
import Child from "./child";

const Myself = () => {
  const count = useWatchCounter();
  const setCount = useUpdateCounter();
  const countUp = () => setCount((prev: number) => ++prev);
  return (
    <div className={scss.component}>
      <GoBack />
      <br />
      <br />
      <ul>
        <li>Updating the screen</li>
        <ul>
          <li>Sharing data between components</li>
        </ul>
      </ul>
      <br />
      <Box
        sx={{
          width: "100%",
          p: 2,
          border: "1px dashed grey",
          borderRadius: "20px",
          backgroundColor: "orange",
          "&:hover": {
            backgroundColor: "white",
            opacity: [0.9, 0.8, 0.7],
          },
        }}
      >
        Myself({count})
        <Child />
      </Box>
      <br />
      <ul>
        <li>Check the sharing data (Click below button)</li>
      </ul>
      <br />
      <Button
        variant="contained"
        size="medium"
        color="primary"
        onClick={() => countUp()}
      >
        Clicked {count} times.
      </Button>
    </div>
  );
};

export default Myself;

5-1-6. src/app/hooks/hook03/page.tsx

"use client";

import { CounterProvider } from "./counter-provider";
import Myself from "./myself";

const Hook03 = () => {
  return (
    <CounterProvider>
      <Myself />
    </CounterProvider>
  );
};

export default Hook03;

5-1-7. src/app/hooks/page.tsx

"use client";

import React from "react";
import { Link } from "@mui/material";

import scss from "./page.module.scss";

const Hooks = () => {
  return (
    <div className={scss.components}>
      <ul>
        <li>
          <Link href="/hooks/hook01" underline="hover">
            Hook01
          </Link>
        </li>
        <li>
          <Link href="/hooks/hook02" underline="hover">
            Hook02
          </Link>
        </li>
        <li>
          <Link href="/hooks/hook03" underline="hover">
            Hook03
          </Link>
        </li>
      </ul>
    </div>
  );
};

export default Hooks;

6. サーバーを起動

npm run dev

7. ブラウザで確認

  • http://localhost:3000

8. ディレクトリの構造

.
├── README.md
├── next-env.d.ts
├── next.config.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
│   ├── next.svg
│   └── vercel.svg
├── src
│   ├── app
│   │   ├── components
│   │   │   ├── component01
│   │   │   │   ├── page.module.scss
│   │   │   │   └── page.tsx
│   │   │   ├── component02
│   │   │   │   ├── page.module.scss
│   │   │   │   └── page.tsx
│   │   │   ├── component03
│   │   │   │   ├── page.module.scss
│   │   │   │   └── page.tsx
│   │   │   ├── page.module.scss
│   │   │   └── page.tsx
│   │   ├── events
│   │   │   ├── event01
│   │   │   │   ├── page.module.scss
│   │   │   │   └── page.tsx
│   │   │   ├── page.module.scss
│   │   │   └── page.tsx
│   │   ├── favicon.ico
│   │   ├── globals.css
│   │   ├── globals.scss
│   │   ├── hooks
│   │   │   ├── hook01
│   │   │   │   ├── page.module.scss
│   │   │   │   └── page.tsx
│   │   │   ├── hook02
│   │   │   │   ├── page.module.scss
│   │   │   │   └── page.tsx
│   │   │   ├── hook03
│   │   │   │   ├── child.tsx
│   │   │   │   ├── counter-provider.tsx
│   │   │   │   ├── grandchild.tsx
│   │   │   │   ├── myself.tsx
│   │   │   │   ├── page.module.scss
│   │   │   │   └── page.tsx
│   │   │   ├── page.module.scss
│   │   │   └── page.tsx
│   │   ├── layout.module.scss
│   │   ├── layout.tsx
│   │   ├── page.module.scss
│   │   └── page.tsx
│   ├── lib
│   │   ├── common
│   │   │   ├── definitions.ts
│   │   │   └── sidebar-links.tsx
│   │   ├── components
│   │   │   ├── alert-snackbar.tsx
│   │   │   ├── go-back.tsx
│   │   │   └── spacer.tsx
│   │   ├── footer.tsx
│   │   ├── header.tsx
│   │   ├── sidebar.tsx
│   │   └── utils
│   │       └── util.ts
│   └── scss
│       └── common
│           ├── _index.scss
│           ├── _mixin.scss
│           ├── _mq.scss
│           └── _variables.scss
├── tailwind.config.ts
└── tsconfig.json

19 directories, 54 files

9. 備考

今回はHooksのuseContextを使いコンポネント間で値を共有する内容でした。

10. 参考

投稿者プロフィール

Sondon
開発好きなシステムエンジニアです。
卓球にハマってます。

関連記事

  1. 【NextJS】Button・IconButton・LoadingBu…

  2. 【NextJS】NextJS・TypeScript・Apollo Cl…

  3. 【NextJS】Local Storage

  4. 【NextJS】Error Handling

  5. 【NextJS】TextField

  6. 【NextJS】Metadata(Head,Title)・Script…

最近の記事

制作実績一覧

  1. Checkeys