const data = React.useState();
console.log(data) => [undefined, f]
useState 훅은 constant 값과 해당 constant 값을 변경할 수 있는 함수를 제공한다.
함수를 제공하는 이유는 함수가 해당 constant 를 사용하는 DOM 을 자동으로 리렌더링할 수 있는 기능을 포함하고 있기 때문이다.
일반적인 변수를 선언하여 view 단에서 사용하면 view 가 업데이트 되지 않는 것을 확인할 수 있다.
단, 여기서 리렌더링이란 컴포넌트 전체가 리렌더링 되는 것은 맞지만 변화된 부분만 리렌더링 됨을 의미한다.
// 일반 예제
// console.log(counter) 시 값은 업데이트 되지만, 화면에서 보여지는 숫자는 업데이트 되지 않음을 확인할 수 있다.
function App() {
const counter = 0;
const onClick = () => {
counter = counter + 1;
}
return (
<div>
<h3 id="title">Total clicks: {counter}</h3>
<button onClick={onClick} >Click me</button>
</div>
)
}
ReactDOM.render(<App />, root);
// State 사용 예제
// setCounter 함수로 counter 값을 업데이트할 경우 자동으로 리렌더링이 발생하여 화면에서 보여지는 숫자가 증가함을 확인할 수 있다.
function App() {
const [counter, setCounter] = React.useState(0);
const onClick = () => {
setCounter(counter + 1) // 개선 필요
}
return (
<div>
<h3 id="title">Total clicks: {counter}</h3>
<button onClick={onClick} >Click me</button>
</div>
)
}
ReactDOM.render(<App />, root);
// State 사용 개선 예제
// setCounter 함수로 counter 값을 업데이트 할 시, 첫번째 인자로 넘어오는 '현재값' 을 이용하여 함수를 넘겨주는 것이 좋다.
// current 로 받아오는 값은 반드시 '현재값' 임을 보장할 수 있다.
function App() {
const [counter, setCounter] = React.useState(0);
const onClick = () => {
setCounter((current) => current + 1)
}
return (
<div>
<h3 id="title">Total clicks: {counter}</h3>
<button onClick={onClick} >Click me</button>
</div>
)
}
ReactDOM.render(<App />, root);
두 번째 방법이 더 안전한 이유는 다음과 같다:
상태의 비동기성: React의 상태 업데이트는 비동기적으로 일어날 수 있다. 즉, 여러 상태 업데이트가 한꺼번에 일어나면 React는 성능 최적화를 위해 여러 상태 변경을 배치(batch)로 처리할 수 있다. 이 경우, counter 변수에 직접 접근해서 상태를 업데이트하면, 업데이트가 시작될 때의 상태 값에 기반한 계산이 되므로, 연속된 상태 업데이트가 서로를 덮어쓸 수 있다.
상태 의존성의 최소화: 함수를 전달하는 방식을 사용하면, 해당 업데이트가 실행될 때의 최신 상태 값을 React가 자동으로 제공한다. 이는 상태 업데이트 로직이 현재의 상태 값에 직접 의존하지 않도록 하여, 코드의 예측 가능성과 유지 보수성을 향상시킨다.
클로저 문제: React 컴포넌트 함수가 실행될 때, 상태와 props는 해당 렌더링 주기에 "캡처"된다. 이로 인해, 이벤트 핸들러나 비동기 함수 내에서 직접 상태 값을 참조할 경우, 예상치 못한 클로저 문제가 발생할 수 있다. 즉, 핸들러나 비동기 함수가 실행될 때 상태 값이 업데이트되지 않은 "오래된" 값일 수 있다. 함수를 사용하는 방식은 항상 최신 상태 값을 참조하게 해준다.
따라서, 특히 상태 업데이트가 이전 상태에 의존적인 경우(예: 카운터 증가) 함수를 통해 상태를 업데이트하는 것이 더 안전하고 권장되는 방법이다.