【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. 参考

投稿者プロフィール

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

関連記事

  1. 【NextJS】Error Handling

  2. 【NextJS】SassとTypescriptでレイアウトを構成

  3. 【NextJS】Redux

  4. 【NextJS】Hooks-useContext

  5. 【NextJS】FullCalendar

  6. 【NextJS】Hooks-useReducer

最近の記事

  1. AWS
  2. AWS
  3. AWS
  4. AWS
  5. AWS

制作実績一覧

  1. Checkeys