상태변수(state variable)는 일반적인 Javascript 변수처럼 보이지만, snapshot처럼 동작한다. (what?)
상태변수(state variable)를 새로운 값으로 업데이트 해도 이미 가지고 있는 상태변수는 변경되지 않고 리렌더링이 일어난다.
What is Snpashot?
구글에 검색해 보면 컴퓨터 파일 시스템에서 스냅샷은 과거의 한 때 존재하고 유지시킨 컴퓨터 파일과 디렉터리의 모임이라고 나온다.
즉, 여기서 말하는 snpashot은 previous state들을 의미하는 거라고 유추된다.
state를 set하면 rendering이 trigger된다.
즉 UI가 이벤트에 반응하려면 state를 업데이트해 re-rendering을 trigger해야 user와 intractive한 반응을 할 수 있다.
렌더링이란 React가 컴포넌트, 즉 함수를 호출한다는 뜻이다. (컴포넌트의 reutrn부분에 해당하는 내용들이 render가 되겠지?)
해당 함수(컴포넌트)에서 반환하는 JSX(return하는 react code들)은 시간상 UI의 스냅샷과 같은데, prop
, event handler
, local variable
모두 렌더링 당시의 state를 사용해 계산된다.
즉, component가 render될때 시간에 따른 해당 컴포넌트가 render된 상태를 snapshot 이라고 이해하면 될거같다.
(A component가 초기상태와 어떠한 이벤트에의해서 시간이 흐른뒤의 상태는 다를거고, 각각의 변화에 따른 상태가 각각의 snapshot이 되겠지?)
리액트가 함수를 다시 호출하고 -> 호출된 함수가 변경된 상태의 스냅샷을 반환하고 -> 리액트가 반환된 스냅샷과 이전 스냅샷을 비교해서 새로 반환된 스냡샷과 일치하게 화면을 업데이트
<button onClick={() => {
setNumber(number + 1);
setNumber(number + 1);
setNumber(number + 1);
}}>+3</button>
useState에서도 다루었지만, setState는 무조건 다음에 발생될 렌더링에 대해서만 변경된다.
그래서 첫번째 렌더링에서 number는 0이었고, setNumber(number + 1)
이 3번 호출이 되어도 number는 여전히 0이다.
아직 re-rendering이 이루어 지지 않았고, 해당 렌더링에서(기존의 스냅샷) 이벤트 핸들러의 number
는 항상 0이기 때문.
import { useState } from 'react';
export default function Counter() {
const [number, setNumber] = useState(0);
return (
<>
<h1>{number}</h1>
<button onClick={() => {
setNumber(number + 5);
setTimeout(() => {
alert(number);
}, 3000);
}}>+5</button>
</>
)
}
위 코드가 실행되면 화면에는 즉시 5라고 나오지만 alert에는 5가 아니라 0이 찍힌다.
🔥리액트에 저장된 state는 alert이 실행딜때 변경될 수 있지만, 사용자가 버튼을 누른 시점에 state snpashot을 사용하기 때문에 0이라고 나오는것임! (화면에 5라고 표시되는건 re-render되어서)🔥