
useEffect
이때, useEffect를 사용해서 코드를 다음처럼 수정하면 이벤트 리스너가 최초 렌더 시 한 번만 생성된다.
만약, 의존성 배열로 [value]를 주면 value에 값이 들어갈 때마다 이벤트 리스너가 생성된다.
import React, {useState, useEffect} from 'react'
export default function Ex1() {
const [value, setValue] = useState('');
useEffect(() => {
document.addEventListener('click', () => {
alert(1);
})
}, [])
console.log("컴포넌트 리렌더. 현재 스테이트: ", value);
return (
<input type="number" value={value} onChange={(e)=>{setValue(e.target.value)}} />
)
}
🤔 Mount, Unmount
- Mount: DOM 트리에 올라간 것
- Unmount: 아예 DOM 트리에서 사라진 것
로그인 누르면<User />Mount
로그아웃 누르면<User />Unmount
[]: Mount 됐을 때 최초 1회 실행[value]: value가 바뀔 때마다 실행값이 바뀌는 것들을 의존성 배열에 넣을 수 있다. (prop이나 state) ref 같은 경우에는 값이 변경된다는 개념이 아니므로 넣지 않는다.
다음 코드에서 value에 값을 넣어도(input에 값을 입력해도) 초기에 들어있던 값('')이 alert에 나오게 된다.

useEffect 안에서 state를 사용하고 싶다면 의존성 배열로 [value] 주어야 한다. value가 변경될 때마다 실행되도록!
그런데 바뀐 value에 대해서 사용하고 싶어서 의존성 배열을 [value]로 주었는데, 이렇게 하면 value가 바뀔 때마다 이벤트 리스너가 생성돼서 쌓인다.
'123'을 입력했을 때
- 기대한 결과: alert 1번 나타나기 (123)
- 실제 결과: alert 4번 나타나기 (초기값 -> 1 -> 2 -> 3)
❗ 이때 필요한 것이 clean up이다.
최초로 한 번 렌더된 이후, 리렌더링 될 때
1. return문이 먼저 실행된다.
2. 그리고 바뀐 값에 대해 useEffect가 실행돼서 이벤트 리스너가 등록되는 것이다.
🤔 왜 제일 처음 실행됐을 땐 return문이 실행되지 않을까?
useEffect는 clean up 함수를 잘 들고 있다가value가 바뀌었을 때 실행한다.
그래서 최초로 렌더되었을 때는 clean up 함수가 실행되지 않는 것이다.

setTimeout(), clearTimeout() 이용import React, {useState, useEffect} from 'react'
export default function Ex1() {
const [value, setValue] = useState('');
useEffect(() => {
let timer;
if (value){
timer = setTimeout(() => {
console.log(value);
}, 3000);
}
return () => {
if(timer) {
clearTimeout(timer);
}
}
}, [value]);
return (
<>
<input
type="number"
onChange={(e) => {setValue(e.target.value)}}
/>
</>
);
}
🤔 리액트가 리렌더를 하기 위해 값이 바뀌었는지 판단하는 방법?
array/object(레퍼런스 타입)의 경우, 참조하는 주소가 바뀌었을 때 값이 바뀌었다고 판단한다.
따라서 의존성 배열에 레퍼런스 타입을 넣는 경우, 변경을 감지할 수 있도록 작성해야 한다. (= 참조하는 주소가 바뀌도록 해야 한다.)
value가 바뀌어도 1부터 2억까지 더한 값은 변하지 않으므로 저장해둔다.
useMemouseMemo를 통해서 계산된 값을 저장할 수 있다.
다음 코드는 의존성 배열이 변경되었을 때 메모이제이션을 다시 수행한다.
input에 값이 다시 입력되면 [props.max]가 변경되었으므로 다시 계산한다.input에 값을 입력했을 땐 다시 계산하지 않는다.[props.max, value]로 주면 자식 input이 바뀌었을 때도 불필요한 계산을 하게 된다.
useCallbackuseMemo의 함수 버전이다.useMemo는 콜백함수에서 return 하는 값이 메모이제이션 되는 것useCallback은 콜백함수 자체가 메모이제이션 되는 것
🤔
- 함수를 return할 땐
useMemo,useCallback둘 다- 그 외엔
useMemo
현업에서 대부분의 환경에서는 Memoization을 사용하진 않으므로 그냥 정말! 필요할 때 '아 이런 게 있었지~' 라고 생각할 수 있는 정도면 OK.
