์ง๋ ๋ช์ฃผ๊ฐ ํ๋ก ํธ ๊ฐ๋ฐ์ ์งํํ๋ฉด์ ํ๋ ์ฌ๋ฌ ๊ณ ๋ฏผ๋ค๊ณผ ํด๊ฒฐ๋ค, ๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ ๊ฒ๋ค์ ๊ธฐ๋กํด๋ณธ๋ค. ์ ๋ชฉ์ ๋ญ๋ผ ์ง์ด์ผํ ์ง ํ์ฐธ ๋์ ๊ณ ๋ฏผํ๋ค. ์ ์ ํ ์ ๋ชฉ ์ถ์ฒ ๋ฐ์ต๋๋ค.
1. ๋ ์ด์์
์คํ ๋ฆฌ๋ถ์ ๋์ ํ๋ฉด์ ์ด๊ฑธ ์ด๋ป๊ฒ ํ๋ฉด ์ ์ธ ์ ์์๊น ์๊ฐํ๋ค๊ฐ ์ ์ฒด ํ์ด์ง์์ ์ฐ๋ ์ปจํ ์ด๋์ ๋ ์ด์์์ ๋ชจ๋ํ์์ผ๋ณด๊ธฐ๋ก ํ๋ค. ๋์์ธํ ํ์ด์ง๋ค์ ๋ ์ด์์์ ๋ณด๋ฉด ์ธ๊ฐ์ง๋ก ๋๋ ์ ์๋ค.
[์ ๋ชฉ๊ณผ ์ค๋ช /๋ด์ฉ(์ฃผ๋ก ์ธํ)/๋ค์์ผ๋ก ๋ฒํผ]์ผ๋ก ์ด๋ฃจ์ด์ง ํ์ด์ง, [์ ๋ชฉ๊ณผ ์ค๋ช /๋ด์ฉ(์๋งค ๊ด๋ จ ์ ๋ณด)]๋ก ์ด๋ฃจ์ด์ง ํ์ด์ง, ๊ทธ๋ฆฌ๊ณ [ํฐ์ผ ์ฝํ ์ธ ] ํ๋๋ก๋ง ์ด๋ฃจ์ด์ง ํ์ด์ง. ๊ทธ๋ฆฌ๊ณ ๋ชจ๋ ํ์ด์ง๋ค์๋ ์ํ์ ๋ฐ๋ผ ๋ค๋ก๊ฐ๊ธฐ ๋ฒํผ์ด ์์ ์ ์์ง๋ง ๊ทธ์ ์๊ด ์์ด ํญ์ ๊ทธ๋งํผ์ ์ฌ๋ฐฑ์ ๋์๋ค.
.InfoLayout {
height: 100%;
display: grid;
grid-template-rows: 3fr 4fr;
}
.ProgressLayout {
height: 100%;
display: grid;
grid-template-rows: 3fr 3fr 1fr;
}
.TicketLayout {
height: 100%;
display: grid;
grid-template-rows: 7fr;
}
๊ฐ ๋ ์ด์์์ ๋ง๊ฒ๋ ๋ด๋ถ ์์๋ค์ ๊ทธ๋ฆฌ๋๋ฅผ ์ด์ฉํด ๋น์จ์ ์ ํด์ฃผ์๋ค. ์ด๋ค ๋ ์ด์์์ด๋ ์ง ์ ์ฒด ๊ทธ๋ฆฌ๋ fr๋ค์ ํฉ์ด 7์ด ๋๋๋ก ํ๋ค.
//Container.jsx
/**
* ํฐ์ผ ๋ฐ๊ธ,์ธ์ฆ ๊ณผ์ ์์ TicketWarpContainer์ ์์ ์ปดํฌ๋ํธ๋ก ๋ค์ด๊ฐ๋๋ค
* ์๋จ ๋ค๋ก๊ฐ๊ธฐ๋ฒํผ ์์ญ๊ณผ , ๊ทธ ์์ญ์ ์ ์ธํ ๋๋จธ์ง ์์ญ์ผ๋ก ๋๋์ด์ ธ ์์ต๋๋ค
* grid : 1fr 7fr ์
๋๋ค.
* TopElemnt prop์ผ๋ก TicketTop ์ปดํฌ๋ํธ๋ฅผ ๋ฐ์ผ๋ฉฐ
* children์ผ๋ก TicketLayout, ProgressLayout, InfoLayout ์ค ํ๋์ ๋ ์ด์์์ ์์์ผ๋ก ๋ฐ์ต๋๋ค.
*/
export const TicketContainer = ({ TopElement, children, ...props }) => {
return (
<div className="Ticket-Container" {...props}>
<div className="Ticket-Inner-Container">
<div className="Ticket-Inner-Top">
{TopElement ? TopElement : <TopElement />}
</div>
<div className="Ticket-Inner-Content">{children}</div>
</div>
</div>
);
};
//Container.css
.Ticket-Inner-Container {
box-sizing: border-box;
height: 100%;
padding: 20px 6%;
display: grid;
grid-template-rows: 1fr 7fr;
max-height: 620px;
min-width: 300px;
}
๊ทธ ๋ค์ ๋ ์ด์์์ ์์์ผ๋ก ๋ฐ์ ์ปจํ
์ด๋๋ก ๊ฐ์ผ๋ค. ๊ทธ ์์์ <div className="Ticket-Inner-Top"></div>
์ด๋ผ๋ ๋
์์ด ๋ค๋ก๊ฐ๊ธฐ ๋ฒํผ์ด ์์ด์ผ ํ ์์ญ์ ๋งก์์ค๋ค. ์์์ ์ ์ฒด ๊ทธ๋ฆฌ๋ fr๋ค์ ํฉ์ด 7์ด ๋๋๋ก ํ ์ด์ ๋ ์ฌ๊ธฐ์ ์๋ค. ๋ค๋ก๊ฐ๊ธฐ ๋ฒํผ์ ์์ญ๊ณผ ๋๋จธ์ง ๋ถ๋ถ์ ๋น์จ์ด 1:7์ด ๋์ด์ผ ํ๊ธฐ ๋๋ฌธ์. ์ด์ ์ ์ปจํ
์ด๋์ ๋ ์ด์์๋ค์ ๋ชจ๋ ํ์ด์ง์์ ๋ถ๋ฌ์ ์ฌ์ฉํ ์ ์๋ค.
2. ์ปจํ ์ด๋
๊ธฐ๋ณธ์ ์ผ๋ก ๋ชจ๋ฐ์ผ ํ๋ฉด์ ๋ง์ถฐ์ ๊ธฐํํ์ง๋ง ํฐ ํ๋ฉด์์๋ ๋ถํธํ์ง ์๊ณ ๋ ์ด์๊ฒ ๋ณด์์ผ๋ฉด ํ๋ค. ๊ทธ๋ ๋ค๊ณ ๋ชจ๋ ํ์ด์ง๋ฅผ ์์ ํ ๋ฐ์ํ์ผ๋ก ๋ง๋ค๊ธฐ์๋ ๊ตณ์ด ์ถ์ ์๊ฐ์ด ๋ค์๋ค.
๊ฝค ์ด์๋ค. ๋๋ฆ ๊ฐ์ฑ๋น ์๋ ๋์์ธ์ด๋ผ๊ณ ์๊ฐ์ด ๋ ๋ค. ๋์ํ๋ฉด์ผ๋์ ๋ท ๋ฐฐ๊ฒฝ๋ ๋คํฌ ๊ณ์ด๋ก ๋ฐ๊ฟ์ผ์ง ์๊ฐ๋ง ํ๋ค๊ฐ ์์ง๋ ์ํ๋ค.
์คํ ๋ฆฌ๋ถ์์ ์ง์ ํ์ธํด ๋ณผ ์ ์๋ค.
๋ชจ๋ฐ์ผ์์ 100vh ์คํฌ๋กค์ด ์๊ธฐ๋ ๋ฌธ์ .
์น์ด์ง๋ง ์ฑ์ฒ๋ผ ์ธ ์ ์๋๋ก ํ ๋์์ธ์์ ๊ฐ์ฅ ์ค์ํ๊ฒ ์คํฌ๋กค์ด ์๊ธฐ์ง ์๋๋ก ํ๋ ๊ฑฐ์๋ค. ๊ทธ๋์ ์ปจํ ์ด๋์ height๋ฅผ 100vh๋ก ์ฃผ์๋๋ฐ ์ด ๋ถ๋ถ์์ ๋ฌธ์ ๊ฐ ์๊ฒผ๋ค. ์ผ๋ฐ์ ์ธ ๋ฐ์คํฌํฑ ๋ธ๋ผ์ฐ์ ์์ ์ ์์ ์ผ๋ก ๋ณด์์ง๋ง, ์์ดํฐ ์ฌํ๋ฆฌ ๊ฐ์ ๋ธ๋ผ์ฐ์ ์์๋ ์คํฌ๋กค์ด ์๊ฒผ๋ค. 100vh์ผ๋ ์ฃผ์์ฐฝ๊ณผ ํ๋จ๋ฐ๊ฐ ๋ทฐํฌํธ์ ํฌํจ๋๊ธฐ ๋๋ฌธ์ด๋ผ๊ณ ํ๋ค.
//index.js
const setScreenSize = () => {
let vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
};
setScreenSize();
index.js์ ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ๋ฃ๋๋ค. window.innerHeight
๋ก ํ์ฌ ๋ทฐํฌํธ์ ๋์ด๋ฅผ ๊ฐ์ ธ์ ์๋ก์ด vh์ ๋จ์๋ก ์ผ๋๋ค. setProperty
๋ก '--vh' ๋ผ๋ css ๋ณ์๋ฅผ ๋ง๋ค์ด ์ฌ์ฉํ ์ ์๋ค.
.Ticket-Container-Wrap {
width: 100vw;
height: calc(var(--vh, 1vh) * 100);
display: flex;
justify-content: center;
align-items: center;
}
css ์์ฑ์ ์์ ๊ฐ์ด ๊ฐ์ ธ์ ์ฌ์ฉํ ์ ์๋ค. ์ฒซ ๋ฒ์งธ ์ธ์์์ ์ฐธ์กฐํ๋ ์ฌ์ฉ์ ์ง์ ์์ฑ์ด ์ ํจํ์ง ์์ ๊ฒฝ์ฐ ํจ์๋ ๋ ๋ฒ์งธ ๊ฐ์ ์ฌ์ฉํ๋ค. ์ฐธ๊ณ . ์ด ๋ถ๋ถ์ ๋ ์ค๊ฐ ํด๊ฒฐํด์ค ๋ถ๋ถ์ด๋ค.
3. ๋ชจ๋ฌ
๋ชจ๋ฌ์ฐฝ์ ๊ฐ์ธ์ ์ผ๋ก ์ข์ํ๋ ๋์์ธ ์ค ํ๋์ด๋ค. ๋ง์ ์ ๋ณด๋ฅผ ๋ฃ์ด์ผ ํ ๋ ์๊ธดํ๊ฒ ์ฌ์ฉํ๋ค.
import React from 'react';
const ModalComponent = ({ children }, ref) => {
return (
<div className="modal hidden" ref={ref}>
<div
className="modal-overlay"
onClick={() => {
ref.current.classList.add('hidden');
}}
></div>
<div className="modal-content">{children}</div>
</div>
);
};
export default React.forwardRef(ModalComponent);
ModalComponent.js์,
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 100;
display: flex;
justify-content: center;
align-items: center;
}
.modal-overlay {
background-color: rgba(0, 0, 0, 0.8);
-webkit-backdrop-filter: blur(15px);
backdrop-filter: blur(15px);
position: absolute;
width: 100%;
height: 100%;
}
@media screen and (min-width: 600px) {
.modal-overlay {
width: calc(var(--containerWidth) - 3px);
height: calc(var(--containerHeight) - 3px);
border-radius: 15px;
}
}
.hidden {
display: none;
}
css ํ์ผ์ด๋ค.
setProperty๋ฅผ ์ด์ฉํด์ ๋ชจ๋ฌ ์ค๋ฒ๋ ์ด ์ค์ ํ๊ธฐ.
์์์ ๋ฐฐ์ด setProperty
๋ฅผ ์ฌ๊ธฐ์ ์ ์จ๋จน์๋ค. position:absolute;
์ ํจ๊ป width์ height๋ฅผ ๋ชจ๋ 100%๋ก ์ฑ์ ์ ์ฒด ํ๋ฉด์ ์ด๋ก๊ฒ ๋ง๋ค์๋ค. ํ์ง๋ง ๋์ ํ๋ฉด์์ ๋ชจ์๋ฆฌ๊ฐ ๋ฅ๊ทผ ์ฌ๊ฐํ ์ปจํ
์ด๋ ์์๋ง ์ฑ์์ ธ์ผ ํ๋ค.
export const handleResize = () => {
const [container] = document.getElementsByClassName('Ticket-Container');
if (!container) return;
document.documentElement.style.setProperty(
'--containerHeight',
`${container.clientHeight}px`
);
document.documentElement.style.setProperty(
'--containerWidth',
`${container.clientWidth}px`
);
์ปจํ ์ด๋๋ฅผ ๊ฐ์ ธ์ ์๋ฆฌ๋จผํธ์ ๋์ด์ ๋๋น๋ฅผ css ๋ณ์์ ๋ฃ์ด๋๊ณ ,
useEffect(() => {
handleResize();
window.addEventListener('resize', handleResize);
return () => {
// cleanup
window.removeEventListener('resize', handleResize);
};
}, []);
์ปดํฌ๋ํธ์์ ์ด๋ฒคํธ๋ฆฌ์ค๋์ ์ฝ๋ฐฑ์ผ๋ก ๋ฌ์์ฃผ์๋ค.
์ด์ ๋ธ๋ผ์ฐ์ ์ฌ์ด์ฆ๊ฐ ๋ฐ๋ ๋๋ง๋ค ๋งค๋ฒ css ๋ณ์์ ๊ฐ์ด ๋ฐ๋๋ฉด์ modal-overlay์ ๋๋น์ ๋์ด ๊ฐ์ด ์ ์ ํ๊ฒ ์ ์ง๋๋ค.
ํ์ ์ปดํฌ๋ํธ๋ก ref ์ ๋ฌํ๊ธฐ.
์ ๋ชจ๋ฌ ์ฝ๋๋ฅผ ๋ค๋ฅธ ๊ณณ์์๋ ์ฌ์ฉํด์ผํ ์ผ์ด ์์ด์ ์ปดํฌ๋ํธ๋ฅผ ๋ฐ๋ก ๋บ๋ค. ๊ทธ๋ฌ๋๋ ์ ๋๋ ๋ชจ๋ฌ์ด ๊ฐ์๊ธฐ ์๋๋๊ฒ ์๋๊ฐ.. className์ ๋ค๋ฃจ๊ธฐ ์ํด์ ๋ฌ์๋จ๋ ref๊ฐ ์ ๋ฌ์ด ์๋ผ์ ์๊ธด ๋ฌธ์ ์๋ค.
๊ณต์๋ฌธ์์์ ๊ทธ๋ ๋ค๊ณ ํ๋.. forwardRef
๋ฅผ ์ฌ์ฉํด๋ณด์๋ค. export ํ๊ธฐ ์ ์ ํจ์ํ ์ปดํฌ๋ํธ๋ฅผ forwardRef
๋ก ๊ฐ์ธ์ ๋ณด๋ด์ฃผ์๋ค. ์ด์ ๋ถ๋ชจ ์ปดํฌ๋ํธ์์ ๋ชจ๋ฌ ์ปดํฌ๋ํธ์ ref๋ฅผ ์ ๋ฌํ ์ ์๋ค.
4. input ์ปดํฌ๋ํธ
๋ฐฐ๋ฆฌ์์ด์ ์ด ๋ง์์ ๊ทธ๋ฐ์ง ์คํ ๋ฆฌ๋ถ์์ input ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค๋ฉด์ ์ ๋ํ ์ค๋ ๊ฑธ๋ ธ๋ค. ๋๋ถ์ ๋ง์ ๋๋ ๊ฒฐ๊ณผ๋ฌผ์ด ๋์๋ค.
์๋ focus, ์๋ blur
์ฒ์ ํฐ์ผ ์๋งค ๊ณผ์ ๋์์ธ์ ํ๋ฉด์ ๊ฐ์ฅ ํ๋ค์๋ ๋ถ๋ถ์ '๋ค์์ผ๋ก' ๋ฒํผ์ด์๋ค. ๋ฒํผ์ ์์น๋ ์์๋๋ก ๊ณ์ ์์ง์ฌ๋ณด๊ณ ๋ฒํผ์ ๋์์ธ๋ ๋ฐ๊ฟ๋ณด๊ณ ํ๋ฉด์ ์ผ๋จ ์ด๋ฐ ๊ฒฐ๊ณผ๋ฌผ์ด ๋์์ง๋ง.. ์ข ๋ ์ข์ ๋ฐฉ๋ฒ์ด ์์์ํ ๋ฐ.
๋ค์์ผ๋ก ๋์ด๊ฐ๋ ํ๋ฉด์ด ์ค๋ฅธ์ชฝ์์ ์ผ์ชฝ์ผ๋ก ์ฌ๋ผ์ด๋ํ๋ ์ ๋๋ฉ์ด์ ์ด ์์์ผ๋ฉด ์ข๊ฒ ๋ค๋ ์๊ฒฌ๊ณผ, ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๋ฒํผ์ด ์ค๋ฅธ์ชฝ ๋ฐ์ ์์์ผ๋ฉด ์ข๊ฒ ๋ค๋ ์๊ฒฌ์ด ์์ด์ ๋ฒํผ ์์น๋ฅผ ์ ๋ ๊ฒ ๋์๋ค. ์์ง๊ฐ ๋ฟ๊ธฐ์๋ ํธํ ์์น์๋ค. ๋ณด๊ธฐ์ ์ด๋ปค์ง๋ง ๋ฌธ์ ๊ฐ ํ๋ ์์๋ค. ๋ชจ๋ฐ์ผ์์ ์ ํ์ด์ง๋ฅผ ๋ณด๋ฉด ํคํจ๋์ ๋ค์์ผ๋ก ๋ฒํผ์ด ๊ฐ๋ ค์ง๊ฒ ๋๋ค.
์ธํ์ ํฌ์ปค์ค๊ฐ ๋๋ฉด ์ ๋๋ฉ์ด์
๊ณผ ํจ๊ป ๋ณด๋ผ์ ์ค๋ก ๋ฐ๋๋ค. ์ฒ์ ํ์ด์ง๊ฐ ๋ ๋๋ง๋ ๋ ์ธํ์ ์๋์ผ๋ก ํฌ์ปค์ค๊ฐ ๋๋๋ก ํ๋ค. (๋ชจ๋ฐ์ผ ํ๋ฉด์์ ๋ฐ๋ก ํค๋ณด๋๊ฐ ์ฌ๋ผ์จ๋ค ๋ผ๋ ์๊ฐ์ผ๋ก ์ฝ๋๋ฅผ ๋ฃ์์ง๋ง ์ค์ ๋ก ํค๋ณด๋๊ฐ ์ฌ๋ผ์ค์ง๋ ์์๋ค. ๋ธ๋ผ์ฐ์ ๋จ์์ ๋ง๋๊ฐ๋ณด๋ค.)
์ธํ์ ์๋ฅผ ๋ค์ด ์ธ์ฆ๋ฒํธ ๊ธธ์ด์ธ 6๊ธ์๊ฐ ์
๋ ฅ๋๋ฉด ๋ค์ ์๋์ผ๋ก ํฌ์ปค์ค๊ฐ ํ๋ฆฌ๋๋ก ํ๋ค. focus()
์ blur()
๋ฉ์๋๋ก ๋์ํ๋ค. ๋ชจ๋ฐ์ผ ํ๋ฉด์์ ์๋์ผ๋ก ํค๋ณด๋๊ฐ ๋ด๋ ค๊ฐ๋ค. ํค๋ณด๋๋ฅผ ์ง์ ๋ด๋ ค์ผ ํ๋ ๋ถํธํจ ์์ด '๋ค์์ผ๋ก' ๋ฒํผ์ ์ฝ๊ฒ ๋๋ฅผ ์ ์๋ค.
์ด ์ญ์ ์คํ ๋ฆฌ๋ถ์์ ์ง์ ์ฌ์ฉํด๋ณผ ์ ์๋ค.
๊ต์ฅํ ํธํ๋ค. ์ ํด์ค length๋งํผ ์ ๋ ฅํ๋ฉด ์์ ์ ๋ ฅ์ ์ ํํ๋ฉด์ ํด๋ผ์ด์ธํธ๋จ์์ ๋ณด๋ด๋ ๊ฐ๋ค์ ํ๋ฒ ๋ ๊ฒ์ฌํด์ฃผ๋ ์ญํ ๋ ํด์ค๋ค. ๊ฝค ์ด์๊ธฐ๋ ํ๋ ๋งค์ฐ ๋ง์กฑํ๋ ๋ถ๋ถ์ด์๋ค.
input border ์ ๋๋ฉ์ด์
์ ๋๋ฉ์ด์
์์ฒด๋ณด๋ค ์ ๋ณด๋ผ์ ๋ง๋๊ธฐ ์์น๋ฅผ ์ก๋๊ฒ ์ด๋ ค์ ๋ค. ็ด ์ ํํ๋ก ๊ทธ๋ฆฌ๋๋ฅผ ๋ฐฐ์นํ๋ค. grid-column: span 3;
์ผ๋ก ํ๋์ ์์๊ฐ ๊ทธ๋ฆฌ๋ ์ฌ๋ฌ ์นธ์ ์ฐจ์งํ๊ฒ ํ ์ ์์๋ค. ์ด์ ๊น์ง ๋จ์ํ grid-template-
์ผ๋ก ๋น์จ๋ง ๊ณ ์ ํด์ฃผ๋ ์ฉ๋๋ก ๊ทธ๋ฆฌ๋๋ฅผ ์ผ์๋๋ฐ, ๊ทธ๋ฆฌ๋๊ฐ ์ด๋ ๊ฒ ํธํ๊ณ ์ข์๊ฑฐ์๋ค๋.
์ ๋๋ฉ์ด์ ์์ฒด๋ ์ด๋ ๊ฒ ์ค ์ ์๋ค.
.input-box ~ .border-animate {
margin: 0 auto;
width: 0%;
height: 2px;
transition: 0.4s;
}
.input-box:focus ~ .border-animate {
width: 100%;
height: 2px;
background-color: #bf94e4;
}
~(๋ฌผ๊ฒฐ) ์ ํ์๋ ์ฒ์ ์์๋ค. A~B ๋ก ์ฌ์ฉํ์ ๋ Aํ๊ทธ์ ํ์ ๊ด๊ณ์ ์๋ ๋ชจ๋ Bํ๊ทธ๊ฐ ์ ํ๋๋ค.
์ธ์ฆ๋ฒํธ ์ฌ์ ์ก 3๋ถ ํ์ด๋จธ
์ด๊ฒ ์๊ฐ๋ณด๋ค ์๊ทผ ๊น๋ค๋กญ๋๋ผ.
export const Timer = ({ time, setTime }) => {
const [isRunning, setIsRunning] = useState(true);
const savedCallback = useRef();
const callback = () => {
setTime(time - 1);
};
useEffect(() => {
savedCallback.current = callback;
});
useEffect(() => {
const tick = () => {
savedCallback.current();
console.log('tick');
};
let timer;
if (isRunning) {
timer = setInterval(tick, 1000);
}
return () => clearInterval(timer);
}, [isRunning]);
useEffect(() => {
if (time == 0) {
setIsRunning(false);
}
}, [time]);
return (
<div className="indicator">
{parseInt(time / 60)}:{('00' + parseInt(time % 60)).slice(-2)}
</div>
);
};
time ์ํ๋ฅผ ๋ฐ์์์ setInterval()
๋ก 1์ด๋ง๋ค ์ํ๋ฅผ ์
๋ฐ์ดํธํด์ฃผ๋ ค๊ณ ํ๋๋ฐ 2:59์์ ๋ฉ์ถฐ๋ฒ๋ฆฌ๋ ์ผ์ด ์๊ฒผ๋ค.
๋ฌธ์ ๋ useEffect๊ฐ count๋ฅผ ์ฒซ ๋ ๋์์ ์ก์๋ฒ๋ฆฌ๋ ํ์ ๋๋ฌธ์ ์ผ์ด๋ฉ๋๋ค. ์ฒซ ๋ ๋์์ count๋ 0์ ๋๋ค. ์ดํํธ๋ฅผ ์ฌ์ ์ฉํ์ง ์์์ setInterval์ ์๋ ํด๋ก์ ๊ฐ ํญ์ ์ฒซ ๋ ๋์ count๋ฅผ ์ฐธ์กฐํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ count + 1์ ๊ณ์ 1์ด ๋๋ ๊ฒ์ด์ฃ .
๋ผ๊ณ ํ๋ค. ์ฐธ๊ณ . ๋งค ๋ ๋๋ง๋ง๋ค ๋ฐ๋๋ time ์ํ๋ฅผ ref์ ๋ด์๋๊ณ setInterval()
ํจ์์ ์ฝ๋ฐฑ์ ์ฌ์ฉํ๋ค. ref๋ ์ปดํฌ๋ํธ ์ฌ์ดํด ์์์ ๊ฐ์ด ์ ์ง๊ฐ ๋๊ธฐ ๋๋ฌธ์ ์ฌ๋๋๋ง๋๋๋์ ๊ฐ์ด ๋ณดํธ๋๋ค.
time์ด 0์ด ๋๋ฉด isRunning state๋ฅผ false๋ฅผ ๋ฐ๊พผ๋ค. useEffect ํ
์์ isRunning ๊ฐ์ด ๋ฐ๋๋๊ฑธ ๋ณด๊ณ 0์ด ๋๋ฉด clearInterval()
๋ฅผ ์คํํ๋ฉฐ ํ์ด๋จธ๋ฅผ ์ข
๋ฃํ๋ค.