여러분들은 렌더링
을 뭐라고 생각하시나요?
어떤 조건에서 렌더링
이 일어 나는 지에 대해 알아보고,
렌더링
을 나만의 언어로 이해 해본 경험을 나눠 볼까 합니다.
리액트에서의 렌더링
은 생각해보면,
특정 조건에서 DOM Tree
를 업데이트 하는 것으로 볼 수 있습니다.
Props
가 변경 되었을 때State
가 변경 되었을 때forceUpdate()
함수를 실행 하였을 때부모 컴포넌트가 렌더링
되었을 때리액트는 위와 같은 조건에서 렌더링이 일어납니다.
그렇다면, 문제를 하나 내보겠습니다.
function Counter() {
const [count, setCount] = useState(0);
function handleAlertClick() {
setTimeout(() => {
alert('You clicked on: ' + count);
}, 3000);
}
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
<button onClick={handleAlertClick}>
Show alert
</button>
</div>
);
}
위와 같은 코드가 있습니다.
아래와 같은 동작을 실행 시켰을 때,
결과는 어떻게 될까요?
You clicked 3 times
You clicked 5 times
둘 중에 어떤 결과가 나올까요?
직접 해봅시다!
왜 3이 출력될까요?
이를 이해하기 위해서는 한 가지 재밌는 발상을 해 볼 수 있습니다.
입니다.
렌더링은 스크린 샷
이라는 생각을 가지고 저희가 한 행동을 다시 한번 짚어 봅시다.
A 스크린 샷에 있을 때 버튼을 클릭해서 count 라는 상태를 변경해서 렌더링이 일어났습니다.
(count === 0 → count === 1)
B 스크린 샷에 있을 때 버튼을 클릭해서 count 라는 상태를 변경해서 렌더링이 일어났습니다.
(count === 1 → count === 2)
C 스크린 샷에 있을 때 버튼을 클릭해서 count 라는 상태를 변경해서 렌더링이 일어났습니다.
(count ===2 → count === 3)
D 스크린 샷에 있을 때, alert 버튼을 클릭 했습니다.
(count === 3)
D 스크린 샷에 있을 때 버튼을 클릭해서 count 라는 상태를 변경해서 렌더링이 일어났습니다.
(count === 3 → count === 4)
E 스크린 샷에 있을 때 버튼을 클릭해서 count 라는 상태를 변경해서 렌더링이 일어났습니다.
(count ===4 → count ===5)
저희는 (4) 번에서 alert 버튼을 클릭해서, 그 때의 상태를 조회 했습니다.
그 때의 count의 값은 3 입니다.
alert 버튼을 클릭하면 그때 그 당시의 count값을 조회합니다.
그래서 3이 나오는 것입니다.
위와 같은 실험 결과로 아래와 같은 생각을 해볼 수 있습니다.
위와 같은 생각을 useCallback
함수에 똑같이 대입해 볼게요.
useCallback의 간단한 정의입니다.
useCallback(func, deps);
해석 해보면,
리액트는 랜더링이 될 때 마다, 함수를 다시 만들어.
근데, 난 이 함수를 다시 만들기가 싫어!
그니깐 나는 특정 값이 바뀌지 않을때는 이 함수를 다시 만들지 않을 거야!
그러면, 너는 나한테 특정 값을 알려줘.
내가 특정 값이 바뀌었을 때만 다시 함수를 다시 만들게!
이런 내용의 Hook 인데요,
이를
라는 원칙에 대입해서 해석해 볼게요.
문제를 또 하나 내 보겠습니다.
위와 같은 컴포넌트가 있습니다.
버튼을 3번 클릭 했을 때, 어떤 결과가 나올까요?
직접 해봅시다.
이를 그림으로 이해해 봅시다.
A 스크린 샷에 있을 때 버튼을 클릭해서 appleNum
이라는 상태를 변경해서 렌더링이 일어났습니다.
하지만, useCallback
으로 둘러 쌓여진 getApples()
함수는 재활용 합니다.
(appleNum
=== 1 → appleNum
=== 2)
B 스크린 샷에 있을 때 appleNum
은 2 입니다.
하지만, getApples()
는 A 스크린 샷에 존재합니다.
A 스크린 샷에서 appleNum
은 1이기 때문에, 사과는 한개만 돌려줍니다.
B 스크린 샷에서 appleNum
이라는 상태를 변경해서 렌더링
이 일어납니다.
(appleNum
=== 2 → appleNum
=== 3)
C 스크린 샷에 있을 때 appleNum
은 3 입니다.
하지만, getApples()
는 A 스크린 샷에 존재합니다.
A 스크린 샷에서 appleNum은
1이기 때문에, 사과는 한 개만 돌려줍니다.
저는 이런 방법으로 리액트의 랜더링
과 상태
를 이해했습니다.
제가 잘못 이해 한 것이 있거나, 잘못된 정보가 있다면 꼭 알려 주시길 바랄게요!
참고한 글
[번역] useEffect 완벽 가이드
잘 읽었습니당