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. 参考
- Docs | Next.js (nextjs.org)
- Quick Start – React
- Material UI: React components based on Material Design (mui.com)
投稿者プロフィール
-
開発好きなシステムエンジニアです。
卓球にハマってます。