【NextJS】Hooks-useEffect

1. 概要

前回はHooksのuseContextとuseReducerを使いコンポネント間で値を共有する内容についてでした。今回はuseEffectを使いコンポネントのレンダリングする内容となります。

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

2. nodeのインストール

こちらを参考

3. プロジェクトを作成

こちらを参考

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

こちらを参考

5. ソースコード

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

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

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

5-1-2. src/app/hooks/hook06/play-provider.tsx

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

const PlayWatchContext: Context<boolean> = createContext(false);
const PlayUpdateContext: Context<any> = createContext(false);

export const PlayProvider = ({ children }: any) => {
  const [isPlaying, setIsPlaying] = useState(false);
  return (
    <PlayWatchContext.Provider value={isPlaying}>
      <PlayUpdateContext.Provider value={setIsPlaying}>
        {children}
      </PlayUpdateContext.Provider>
    </PlayWatchContext.Provider>
  );
};

export const useWatchPlay = () => useContext(PlayWatchContext);
export const useUpdatePlay = () => useContext(PlayUpdateContext);

5-1-3. src/app/hooks/hook06/video-player.tsx

import React, { useEffect, useRef } from "react";
import { useWatchPlay, useUpdatePlay } from "./play-provider";

type Props = {
  src: string;
};

const VideoPlayer = (props: Props) => {
  const isPlaying = useWatchPlay();
  const setIsPlaying = useUpdatePlay();

  const { src } = props;
  const ref = useRef<HTMLVideoElement>(null);

  useEffect(() => {
    if (isPlaying) {
      const intervalId = setInterval(() => {
        ref.current?.pause();
        setIsPlaying(!isPlaying);
      }, 7000);
      ref.current?.play();
      return () => clearInterval(intervalId);
    } else {
      ref.current?.pause();
    }
    console.log("VideoPlay is called.");
  }, [isPlaying, setIsPlaying]);

  return <video ref={ref} src={src} loop playsInline />;
};

export default VideoPlayer;

5-1-4. src/app/hooks/hook06/text-box.tsx

import { useState, ChangeEvent } from "react";
import { Divider } from "@mui/material";
import Box from "@mui/material/Box";
import TextField from "@mui/material/TextField";

const TextBox = () => {
  const [text, setText] = useState("");

  const handleChange = (
    e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
  ) => {
    setText(e.target.value);
  };

  return (
    <Box
      sx={{
        width: "100%",
        p: 2,
        border: "1px dashed grey",
        borderRadius: "20px",
        "&:hover": {
          backgroundColor: "pink",
          opacity: [0.9, 0.8, 0.7],
        },
      }}
    >
      <TextField
        fullWidth
        label="Hello"
        color="secondary"
        onChange={handleChange}
      />
      <Divider />
      {text}
    </Box>
  );
};

export default TextBox;

5-1-5. src/app/hooks/hook06/child.tsx

import React from "react";
import { Button, Stack } from "@mui/material";
import PlayArrowIcon from "@mui/icons-material/PlayArrow";
import scss from "./page.module.scss";
import GoBack from "@/lib/components/go-back";
import VideoPlayer from "./video-player";
import { useWatchPlay, useUpdatePlay } from "./play-provider";
import TextBox from "./text-box";

const Child = () => {
  const isPlaying = useWatchPlay();
  const setIsPlaying = useUpdatePlay();
  const handleClick = () => {
    setIsPlaying(!isPlaying);
  };
  return (
    <div className={scss.component}>
      <GoBack />
      <br />
      <br />
      <ul>
        <li>Updating the screen</li>
        <ul>
          <li>useEffect</li>
        </ul>
      </ul>
      <br />
      <Stack spacing={1} sx={{ width: "50%" }}>
        <TextBox />
        <Button
          variant="contained"
          size="medium"
          color="primary"
          endIcon={<PlayArrowIcon />}
          onClick={handleClick}
        >
          {isPlaying ? "Pause" : "Play"}
        </Button>
        <VideoPlayer src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4" />
        This video will be stopped in 7 seconds.
      </Stack>
    </div>
  );
};

export default Child;

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

"use client";

import { PlayProvider } from "./play-provider";
import Child from "./child";

const Hook06 = () => {
  return (
    <PlayProvider>
      <Child />
    </PlayProvider>
  );
};

export default Hook06;

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>
        <li>
          <Link href="/hooks/hook04" underline="hover">
            Hook04
          </Link>
        </li>
        <li>
          <Link href="/hooks/hook05" underline="hover">
            Hook05
          </Link>
        </li>
        <li>
          <Link href="/hooks/hook06" underline="hover">
            Hook06
          </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
│   │   │   ├── component04
│   │   │   │   ├── checkbox-demo.tsx
│   │   │   │   ├── page.module.scss
│   │   │   │   ├── page.tsx
│   │   │   │   ├── radio-demo.tsx
│   │   │   │   └── select-demo.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
│   │   │   ├── hook04
│   │   │   │   ├── page.module.scss
│   │   │   │   └── page.tsx
│   │   │   ├── hook05
│   │   │   │   ├── child.tsx
│   │   │   │   ├── counter-provider.tsx
│   │   │   │   ├── grandchild.tsx
│   │   │   │   ├── myself.tsx
│   │   │   │   ├── page.module.scss
│   │   │   │   └── page.tsx
│   │   │   ├── hook06
│   │   │   │   ├── child.tsx
│   │   │   │   ├── page.module.scss
│   │   │   │   ├── page.tsx
│   │   │   │   ├── play-provider.tsx
│   │   │   │   ├── text-box.tsx
│   │   │   │   └── video-player.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

23 directories, 73 files

9. 備考

今回はHooksのuseEffectを使いコンポネントのレンダリングする内容でした。

10. 参考

関連記事

  1. 【NextJS】Redux-createAsyncThunk

  2. 【NextJS】Canvasを使い、図形を描画

  3. 【NextJS】FullCalendar

  4. 【NextJS】Dynamic Routes

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

  6. 【NextJS】Redux

最近の記事

  1. AWS
  2. AWS
  3. AWS
  4. AWS
  5. AWS
  6. AWS
  7. AWS
  8. AWS

制作実績一覧

  1. Checkeys