어떠한 컴포넌트 있다고 하자
위의 세 경우 특정한 작업을 수행 할 코드를 짜려면 useEffect() 를 사용한다.
인자로 콜백함수를 받으며, 형태는 아래와 같다.
useEffect(() => {
// 여기에 수행할 코드
}, [의존성배열])
의존성 배열은 기준이 되는 해당 값을 하나 넣고 그 값이 변경될때 콜백 함수내 코드가 실행되도록 한다. 의존성배열로 빈배열[]
을 넣는다면 첫 랜더링시 딱 한번만 실행되고 이후로는 실행되지 않는다.
의존성배열을 쓰지 않는 경우엔 컴포넌트가 Mount, Update가 이루어 질 때마다 계속 콜백함수 내 코드가 실행된다.
UseEffect()
사용하면 정리 작업도 해줘야 할 때가 있다.
예를 들어 타이머를 동작했다가 멈춰야 하거나, 이벤트리스너를 등록했다가 이제는 제거해야한다던가 하는 경우가 있을 수 있겠다. 그럴 땐 UseEffect()
안 콜백함수에 return
값으로 함수를 주면 된다. 그 return
되는 함수에 원하는 정리 작업을 작성하면 된다.
형태는 아래와 같다.
useEffect(()=>{
// 구독...
return () => {
// 구독 해지...
}
)
이렇게 함수를 return
하면, 컴포넌트가 UnMount 될때, 또는 다음 랜더링 시 불려질 useEffect()
가 실행되기 이전에 return
안 함수가 실행 된다.
아래와 같은 React 코드가 있다.
어떤 순서대로 실행될까?
function App() {
useEffect(() => {
console.log(1);
}, []);
return ...
}
const OuterBox: FC = () => {
useEffect(() => {
console.log(2);
}, []);
return ...
};
const InnerBox: FC = () => {
useEffect(() => {
console.log(3);
}, []);
return ...
};
useEffect()
는 컴포넌트가 렌더링이 된 후에 실행된다. 따라서 App이 render 되기 위해서는 OuterBox가 먼저 렌더링이 되어야 되고, OuterBox가 완전히 렌더링 되기 위해서는 InnerBox가 렌더링이 되어야 한다. 결론은 최하위에 있는 컴포넌트의 useEffect가 먼저 실행된다.
// 내가 짠 예제 코드
// 간단한 시계 Clock.jsx 컴포넌트를 만들고
// App.js에서 토글식으로 조건부 랜더링 되게 했다.
// ./App.js
import React, { useState } from "react";
function App() {
const [showClock, setShowClock] = useState(false);
return (
<div>
<button onClick={()=>setShowClock(!showClock)}>시계!!!!!</button>
{showClock && <Clock/>}
</div>
)
}
</LikeConsumer>
</LikeProvider>
);
}
export default App;
Clock.jsx 컴포넌트에서는 useEffect() 안에 setInterval을 활용하여
Date() 객체에서 가져온 값을 1초마다 바꿔주도록 했다.
// ./components/Clock.jsx
import React, { useEffect, useState } from "react";
const Clock = () => {
const initialstate = String(new Date()).split("GMT")[0]
const [time, setTime] = useState(initialstate);
useEffect(() => {
const myClock = setInterval(() => {
let value = String(new Date()).split("GMT")[0]
setTime(value);
console.log(value)
}, 1000);
return ( () => {
clearInterval(myClock)
console.log("시계멈춤!!")
}
)
}, []);
return (
<div
style={{
width: "200px",
height: "100px",
border: "2px solid green",
margin: "10px 0",
display: "flex",
justifyContent: "center",
alignItems: "center",
flexDirection: "column",
}}
>
<span>{time}</span>
</div>
);
};
export default Clock;