state
변수는 읽고 쓸 수 있는 일반JavaScript
변수로 보일 수 있다.- 그러나
state
는 스냅샷처럼 동작한다. state
변수를 설정해도 이미 가지고 있는state
변수는 변경되지 않고, 대신 리렌더링이 실행된다.
state
를 설정하면 렌더링이 트리거된다.- 클릭과 같은 사용자 이벤트에 반응하여 사용자 인터페이스가 직접 변경된다고 생각할 수 있다.
- 그러나
React
에서는 이와는 조금 다르게 동작한다. send
를 누르면setIsSent(true)
가React
에UI
를 다시 렌더링하도록 지시한다.- 버튼을 클릭하면 아래와 같은 일들이 발생한다.
onSubmit
이벤트 핸들러가 실행된다.setIsSent(true)
가isSent
를true
로 설정하고 새 렌더링을 큐에 대기시킨다.React
는 새로운isSent
값에 따라 컴포넌트를 다시 렌더링한다.
인터페이스가 이벤트에 반응하려면 state를 업데이트 해야 한다.
import { useState } from 'react'; export default function Form() { const [isSent, setIsSent] = useState(false); const [message, setMessage] = useState('Hi!'); if (isSent) { return <h1>Your message is on its way!</h1> } return ( <form onSubmit={(e) => { e.preventDefault(); setIsSent(true); sendMessage(message); }}> <textarea placeholder="Message" value={message} onChange={e => setMessage(e.target.value)} /> <button type="submit">Send</button> </form> ); } function sendMessage(message) { // ... }
- 렌더링은 그 시점의 스냅샷을 찍는다.
- 렌더링이란
React
가 컴포넌트, 즉 함수를 호출한다는 뜻이다. 해당 함수에서 반환하는 JSX는 시간에 따른 UI의 스냅샷과 같다. - props, 이벤트 핸들러, 로컬 변수는 렌더링 당시의 state를 사용해 계산된다.
- 사진이나 동영상과 달리 반환하는 UI '스냅샷' 은 인터렉티브 하다.
- 여기에는
input
에 대한 응답으로 어떤 일이 일어날지 지정하는 이벤트 핸들러와 같은 로직이 포함된다. React
는 이 스냅샷과 일치하도록 화면을 업데이트하고, 이벤트 핸들러를 연결한다.- 결과적으로 버튼을 누르면 JSX에서 클릭 핸들러가 발동된다.
React
가 컴포넌트를 다시 렌더링할 때React
가 함수를 다시 실행한다.- 함수가 새로운 JSX 스냅샷을 반환한다.
React
가 반환된 스냅샷과 일치하도록 화면을 업데이트 한다.- 컴포넌트의 메모리로서
state
는 함수가 반환된 후 사라지는 일반 변수들과는 다르다. state
는 실제로 외부 함수에 마치 선반(shelf) 이 있는것 처럼,React
자체에 존재한다.React
가 컴포넌트를 호출하면 특정 렌더링에 대한state
의 스냅샷을 제공한다.- 컴포넌트는 해당 렌더링의 state값을 사용해 계산된 새로운 props 세트와 이벤트 핸들러가 포함된 UI의 스냅샷을 JSX에 반환한다.
- 이를 설명하는 간단한 예제가 아래에 있다. 실행을 예측해보자.
number
는 클릭 당 1씩 증가한다.- 위와 같이
state
를 설정하면 다음 렌더링에 대해서만 변경된다. - 첫 번째 렌더링에서
number
는0
이었다. - 따라서 해당 렌더링의
onClick
핸들러에서setNumber(number + 1)
이 호출된 후에도number
의 값은 여전히0
이다. - 이 버튼의 클릭 핸들러가
React
에 지시하는 작업은 아래와 같다. setNumber(number + 1)
:number
는0
이므로setNumber(0 + 1)
React
는 다음 렌더링에서number
를 1로 변경할 준비를 한다.setNumber(number + 1)
:number
는0
이므로setNumber(0 + 1)
React
는 다음 렌더링에서number
를 1로 변경할 준비를 한다.setNumber(number + 1)
:number
는0
이므로setNumber(0 + 1)
React
는 다음 렌더링에서number
를 1로 변경할 준비를 한다.setNumber(number + 1)
를 3번 호출했지만, 이 렌더링에서 이벤트 핸들러의number
는 항상 0이므로state
를 1로 3번 설정했다.


import { useState } from 'react'; export default function Counter() { const [number, setNumber] = useState(0); return ( <> <h1>{number}</h1> <button onClick={() => { setNumber(number + 1); setNumber(number + 1); setNumber(number + 1); }}>+3</button> </> ) }
- 시간 경과에 따른 state
- 아래 코드의 결과는 어떻게 될지 맞춰보자.
import { useState } from 'react'; export default function Counter() { const [number, setNumber] = useState(0); return ( <> <h1>{number}</h1> <button onClick={() => { setNumber(number + 5); alert(number); }}>+5</button> </> ) }
- 이전 상태의
number
가 나타나게 된다.
- 만약 타이머를 설정한다면 어떻게 동작할까?
- 여전히 이전 상태의
number
가 나타난다.
React
에 저장된state
는 알림이 실행될 때 변경되었을 수 있지만, 사용자가 상호작용한 시점에state
스냅샷을 사용하는 것은 이미 예약된 것이다.
state
변수의 값은 이벤트 핸들러의 코드가 비동기적이라도 렌더링 내에서 절대 변경되지 않는다.- 이 값은 컴포넌트를 호출한React가 UI의 스냅샷을 찍을 때 고정된 값이다.