16. useEffect() hook
처음 컴포넌트가 렌더링된 이후, 업데이트로 인한 재렌더링 이후에 실행
src/16/MyComponent1.jsx
// useEffect(function,[dependencies])
// 1. 의존성 배열 생략 시 컴포넌트 업데이트 시마다 실행
// useEffect(()=>{})
// 2. 의존성 배열 비어 있을 경우 마운트와 언마운트시에 단 한번씩만 실행
// useEffect(()=>{},[])
// 3. 컴포넌트 마운트되었을때, 의존성 배열에 있는 변수들 중 하나라도 값이 변경되었을 때 실행
// useEffect(()=>{},[value])
// 4. 함수안에 리턴구문은 컴포넌트가 마운트 해제되기 전에 실행
// useEffect(()=>{ return () => { } })
// uses
// 1. Event Listeners
// 2. DOM 조작
// 3. 구독 (real-time updates)
// 4. API에서 데이터 가져오기
// 5. 컴포넌트가 언마운트 될때 정리 작업
import { useState, useEffect } from "react";
export default function MyComponent_16(){
const [count, setCount] = useState(0);
const [color, setColor] = useState("green");
useEffect(() => {
document.title = `Count: ${count} ${color}`;
return() => {
// some cleanup code
}
},[count,color]);
function addCount(){
setCount(c => c + 1);
}
function subtractCount(){
setCount(c => c - 1);
}
function changeColor(){
setColor(c => c === "green" ? "red" : "green");
}
return(
<>
<p style={ {color:color} }>Count: {count}</p>
<button onClick={addCount}>Add</button>
<button onClick={subtractCount}>Subtract</button><br/>
<button onClick={changeColor}>Change color</button>
</>
)
}
src/16/MyComponent2.jsx
import { useState, useEffect } from "react";
export default function MyComponent_16_2(){
const [width,setWidth] = useState(window.innerWidth);
const [height,setHeight] = useState(window.innerHeight);
// window.addEventListener("resize",handleResize);
// console.log("EVENT LISTENER ADDED");
useEffect(() => {
window.addEventListener("resize",handleResize);
console.log("EVENT LISTENER ADDED");
return () => {
window.removeEventListener("resize",handleResize);
console.log("EVENT LISTENER REMOVED");
}
},[]);
useEffect(() => {
document.title = `Size: ${width} * ${height}`
},[width,height])
function handleResize(){
setWidth(window.innerWidth);
setHeight(window.innerHeight);
}
return(
<>
<p>Window Width: {width}px</p>
<p>Window Height: {height}px</p>
</>
);
}
17. digital clock app
src/17/DigitalClock.jsx
import { useState,useEffect } from "react";
import './DigitalClock.css'
export default function DigitalClock(){
const [time,setTime] = useState(new Date());
useEffect(()=>{
const intervalId = setInterval(()=>{
setTime(new Date());
},1000)
return () => {
clearInterval(intervalId);
}
},[]);
function formatTime(){
let hours = time.getHours();
const minutes = time.getMinutes();
const seconds = time.getSeconds();
const meridiem = hours >= 12 ? "PM" :"AM";
hours = hours % 12 || 12;
return `${padZero(hours)}:${padZero(minutes)}:${padZero(seconds)} ${meridiem}`
}
function padZero(number){
return (number < 10 ? "0" : "" ) + number;
}
return(
<div className="clock-container">
<div className="clock">
<span>{formatTime()}</span>
</div>
</div>
);
}
src/17/DigitalClock.css
body{
background-image: url('../assets/bg1.jpg');
background-position: center;
background-repeat: no-repeat;
background-size: cover;
background-attachment: fixed;
margin: 0;
/* optional */
display: flex;
justify-content: center;
min-height: 100vh;
align-items: center;
}
.clock-container{
backdrop-filter: blur(10px);
width: 100vw;
padding: 10px 0;
}
.clock{
color: white;
font-size: 6rem;
font-weight: bold;
font-family: monospace;
text-align: center;
text-shadow: 3px 3px 5px hsla(0, 0%, 0%, 0.75);
}