passing a function (correct)함수 전달 (올바름) | calling a function (incorrect)함수 호출 (잘못됨) |
<button onClick={handleClick}> | <button onClick={handleClick()}> |
두 번째 예시에서
handleClick()
끝에 있는 ()
은 클릭 없이 렌더링 중에 즉시 함수를 실행합니다.1. 지역 변수는 렌더링 간에 유지되지 않습니다. React는 컴포넌트를 두 번째로 렌더링할 때 지역 변수에 대한 변경 사항을 고려하지 않고 처음부터 렌더링합니다. 2. 지역 변수를 변경해도 렌더링을 발동시키지 않습니다. React는 새로운 데이터로 컴포넌트를 다시 렌더링해야 한다는 것을 인식하지 못합니다.
컴포넌트를 새 데이터로 업데이트하려면 두 가지 작업이 필요합니다
1. 렌더링 사이에 데이터를 유지합니다. 2. 새로운 데이터로 컴포넌트를 렌더링(리렌더링)하도록 React를 촉발합니다.
Hook(훅)
use
로 시작하는 다른 함수useState의 실제 동작 방식
- 컴포넌트가 처음 렌더링됩니다.
- state를 업데이트합니다.
- 컴포넌트가 두 번째로 렌더링됩니다.
동일한 컴포넌트를 두 군데에서 렌더링하면 각 사본은 완전히 격리된 state를 갖게 됩니다!
state는 격리되고 프라이빗합니다.
props와 달리 state는 이를 선언하는 컴포넌트 외에는 완전히 비공개이며, 부모 컴포넌트는 이를 변경할 수 없습니다.
React의 렌더링 동작
1. 렌더링 촉발 (손님의 주문을 주방으로 전달) 2. 컴포넌트 렌더링 (주방에서 주문 받기) 3. DOM에 커밋 (테이블에 주문한 요리 내놓기)
Step 1: Trigger a render
컴포넌트 렌더링이 일어나는데 두 가지 이유
- 컴포넌트의
첫 렌더링
인 경우
- 컴포넌트의
state
가 업데이트된 경우
첫 렌더링
DOM노드로
createRoot
를 호출한 다음 컴포넌트로 render
메서드를 호출하면 된다.state가 업데이트되면 리렌더링합니다
컴포넌트라 처음 렌더링되면 set함수로 state를 업데이트하여 추가 렌더링을 촉발시킬 수 있습니다.
Step 2: React renders your components
- 첫 렌더링에서 React는 루트 컴포넌트를 호출합니다.
- 이후 렌더링에서 React는 state 업데이트에 의해 렌더링이 발동된 함수 컴포넌트를 호출합니다.
Step 3: React commits changes to the DOM
- 초기 렌더링인 경우 React는 appendChild() DOM API를 사용하여 생성한 모든 DOM 노드를 화면에 표시합니다.
- 리렌더링의 경우 React는 필요한 최소한의 작업을 적용하여 DOM이 최신 렌더링 출력과 일치하도록 합니다.
React는 state 업데이트를 하기 전에 이벤트 헨들러의 모든 코드가 실행될 때까지 기다립니다.
다음 렌더링 전에 동일한 state 변수를 여러 번 업데이트하기
export default function Counter() { const [number, setNumber] = useState(0); return ( <> <h1>{number}</h1> <button onClick={() => { setNumber(n => n + 1); setNumber(n => n + 1); setNumber(n => n + 1); }}>+3</button> </> ) }
여기서 n ⇒ n+1는 업데이트 함수라고 부릅니다.
1. React는 이벤트 핸들러의 다른 코드가 모두 실행된 후에 이 함수가 처리되도록 큐에 넣습니다. 2. 다음 렌더링 중에 Reacts는 큐를 순화하여 최종 업데이트된 state를 제공합니다.
setNumber(n => n + 1); setNumber(n => n + 1); setNumber(n => n + 1);
동작방식
setNumber(n ⇒ n+1)
:n ⇒ n+1
함수를 큐에 추가합니다.
setNumber(n ⇒ n+1)
:n ⇒ n+1
함수를 큐에 추가합니다.
setNumber(n ⇒ n+1)
:n ⇒ n+1
함수를 큐에 추가합니다.
다음 렌더링 중에useState
를 호출하면 React는 큐를 순회합니다.number
state는0
이었으므로 React는 이를 첫 번째 업데이터 함수에n
인수로 전달합니다. 그런 다음 React는 이전 업데이터 함수의 반환값을 가져와서 다음 업데이터 함수에n
으로 전달하는 식으로 반복함
queued update | n | returns |
n => n + 1 | 0 | 0 + 1 = 1 |
n => n + 1 | 1 | 1 + 1 = 2 |
n => n + 1 | 2 | 2 + 1 = 3 |
Immer는 어떻게 동작하나요?
Immer
에서 제공하는 draft
는 프록시라는 특수한 유형의 객체로, 사용자가 수행하는 작업을 기록합니다.그렇기 때문에 원하는 만큼 자유롭게 수정할 수 있습니다.
Immer
는 내부적으로 draft
의 어떤 부분이 변경되었는지 파악하고 편집 내용이 포함된 완전히 새로운 객체를 생성합니다.- npm install use-immer를 실행하여 Immer 의존성으로 추가
- import { useState } from ‘react’ ⇒ import { useImmer } from ‘use-immer’로 바꿉니다.