useEffect를 활용하여 컴포넌트가 마운트되었을 때와 언마운트될 때의 동작을 구현합니다.
예를 들어, API 데이터를 불러와서 컴포넌트에 표시하는 작업을 수행합니다.
이 경우엔 자동 새로고침으로 특정 시간마다 계속해서 강아지의 이미지를 새로고침하는 방식으로 구현됐습니다.
useEffect를 통해서 토글 버튼의 동작(isLoading) 감지 후 딜레이를 확인하고 무한 새로고침을 실시하며
토글 버튼을 다시 누를 경우 false를 반영해서 클린업으로 setinterval을 삭제합니다.
useEffect(() => {
const value = Math.min(10, Math.max(1, parseInt(delay) || 1))
let inter;
if(isLoading){
fetchDog()
inter = setInterval(()=>{
fetchDog()
},value*1000)
}
return () => {
if (inter) clearInterval(inter); // intervalId가 존재하면 타이머 중지
};
}, [isLoading])
js 코드
더보기
import { useState, useEffect } from 'react'
import './App.css'
// App.jsx
function App() {
const [dogImage, setDogImage] = useState('')
const [isLoading, setIsLoading] = useState(false)
const [delay, setdelay] = useState('5')
const [error, setError] = useState(null)
// async로 dog 이미지 로딩 기다림
const fetchDog = async () => {
console.log("불러옴")
//새로고침 중임을 확인 true
try {
const response = await fetch('https://dog.ceo/api/breeds/image/random')
const data = await response.json()
setDogImage(data.message)
setError(null)
} catch (err) {
setError('강아지 이미지를 가져오는데 실패했습니다.')
} finally {
}
}
//isrefresh 변경 시 딜레이 세팅하도록 수정정
useEffect(() => {
const value = Math.min(10, Math.max(1, parseInt(delay) || 1))
let inter;
if(isLoading){
fetchDog()
inter = setInterval(()=>{
fetchDog()
},value*1000)
}
return () => {
if (inter) clearInterval(inter); // intervalId가 존재하면 타이머 중지
};
}, [isLoading])
//토글 방식
const toggle =()=>{
//껐다 키기
if (isNaN(delay)){
alert("숫자만 입력해주세요");
}
else setIsLoading(!isLoading)
}
return (
<div className="container">
<h1>🐕 랜덤 강아지 이미지 🐕</h1>
{error && <p className="error">{error}</p>}
{dogImage && (
<div className="dog-img">
<img
src={dogImage}
alt="Random Dog"
className="dog-box"
/>
</div>
)}
<div>
<input type='textbox' className='inputdelay'
value={delay}
onChange={(e) => setdelay(e.target.value)}
placeholder="새로고침 간격"
></input>
<span>초</span>
<div>(최소 : 1, 최대 : 10초)</div>
</div>
<button
onClick={toggle}
className={isLoading?"load":""}
>
{isLoading ? '새로고침\n멈추기' : '새로운\n강아지 보기'}
</button>
</div>
)
}
export default App
css 코드
더보기
#root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
.container{
width: fit-content;
height: fit-content;
display: flex;
flex-direction: column;
align-items: center;
}
.dog-box{
border-radius: 25px;
max-height: 300px;
height: 300px;
object-fit: cover;
}
button.load{
background-color: #888;
}
button {
margin: 20px;
border-radius: 8px;
height: 100px;
width: 200px;
max-height: 100px;
max-width: 200px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1.5em;
font-weight: 800;
background-color: azure;
border-radius: 25px;
font-family: inherit;
cursor: pointer;
transition: border-color 0.25s;
white-space: pre-line;
}
button:disabled {
background: linear-gradient(to bottom, #ffffff, #cccccc);
color: #888;
cursor: not-allowed;
border: 1px solid #ccc;
}
.inputdelay{
width: 100px;
}
:root {
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}
'React > 예제' 카테고리의 다른 글
리액트 앱에서 에러 처리 및 예외 처리 구현하기 (0) | 2025.04.10 |
---|---|
usecontext로 다크 모드 구현 (0) | 2025.04.10 |
컴포넌트 재사용성 - 유튜브 아이템 추가 (0) | 2025.04.09 |
await/async 예제 - 랜덤 강아지 이미지 (0) | 2025.04.08 |
모달 버튼 열고 닫기 (0) | 2025.04.08 |