index.tsx에서 App을 렌더링할 때 보면
const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement)
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
)
이런 식으로 React.StrictMode가 App component를 감싸고 있다.
이거 왜 있는 건가?
공식 문서를 봤더니 React.StrictMode는 어플리케이션 내 잠재적인 문제를 알아내기 위한 도구랬다.
즉, 쟤가 버그가 일어날 거 같은 부분을 알아서 먼저 알려주는 거다.
map 함수를 썼을 때 key 안 넣으면 콘솔창에서 난리치던게 쟤 때문이다.
저 strict mode는 다음과 같은 부분을 도와준다고 한다.
React는 컴포넌트를 렌더링 하기 위해 렌더링, 커밋이라는 두 단계를 거친다.
렌더링 단계에서는 이전과 뭐가 달라졌는지 비교를 한다.
공식 문서를 읽어보면 렌더링은 주방에서 음식을 조리하는 단계, 커밋은 손님에게 음식을 갖다 주는 것에 비유한다.
렌더링은 1. 초기 렌더링, 2. state 업데이트(혹은 부모 컴포넌트의 업데이트) 두 가지로 나뉜다.
import Image from './Image.js';
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'))
root.render(<Image />);
이게 초기 렌더링이다.
초기 렌더링 후에, state setter 함수 등으로 state에 변화가 일어나면 재 렌더링을 한다.
이때 컴포넌트에 업데이트가 일어나면 렌더링 할 것이 차례대로 큐에 들어간다.
비유를 하자면 레스토랑에서 손님이 처음에 주문을 한 후에 목이 말라서(state 변화) 커피를 시키고(render triggering), 배가 덜 차서(state 변화) 디저트를 주문(render triggering)하는 것이다.
commit) 전까지는 아무것도 하지 않는다.렌더링 후에는 React가 DOM을 수정한다.
이게 뭔 소리냐?
export default function Clock({ time }) {
return (
<>
<h1>{time}</h1>
<input />
</>
);
}
이렇게 부모 컴포넌트로부터 현재 시각을 전달 받아 화면에 보여주는 코드가 있다고 하자.
그럼 부모 component의 time이 바뀔 때마다 Clock이 재렌더링될 것이다. 근데 input에 글을 써보면 시간이 바뀔때마다 초기화 되야할 것 같은데 그러지 않는다.
WHY????
왜냐하면 commit 단계에서는 render간의 차이가 있는 노드만 변경하기 때문이다. h1 안에 들어가는 time은 달라지지만, input element는 그대로다. 따라서 input은 재렌더링 되지 않는다.
장황하게 리액트의 렌더링 과정에 대해 설명했다.
React.StrictMode로 컴포넌트를 감싸게 되면 원하지 않는 state 변경과 같은 side effect를 방지하고자 저 렌더링 과정이 두 번 수행된다.
따라서 console.log가 두 번 찍히게 되는 것이다.
그럼 끗~
잘 읽고갑니다!!