background
React5분

state

2024년 11월 18일

State

  • 컴포넌트는 사용자와의 상호작용 결과로 화면 변경이 필요할 때가 많음 만약 사용자가 버튼을 클릭했을 때 다른 이미지를 보여준다고 할때 이미지의 값을 저장할 필요가 있다
  • 이러한 부분을 React에서는 state 라고 부르게 된다
  • React는 state 값의 변화에 따라 컴포넌트를 리렌더링하게 되는데 state 란, 컴포넌트의 리렌더링을 유발하는 트리거가 되는 것이다.

예시

  • 전역 변수로 count 값을 지정하고 버튼 클릭할 때 값을 변경하는 함수를 작성 해보자

    javascript
    export function Counter () {
    	let count = 0;
    	
    	function increaseCount() {
    		count += 1;
    		console.log(count);
    	}
    	
    	function decreaseCount() {
    		count -=1;
    		console.log(count);
    	}
    	
    	return (
    		<div>
    			<button onClick={increaseCount()}>1 더하기</button>
    			<button onClick={decreaseCount()}>1 빼기</button>
    			<p>점수 : {count}</p>
    		</div>
    	)
    }
    
  • 해당 코드는 사용자가 버튼을 클릭하더라도 Count는 0으로 고정되게 되는데 실제로 count의 값이 변경 되지만 화면이 리 렌더링 되지 않기 때문에 보여지는 화면에서는 0으로 고정 되어 있는 것이다.

  • 따라서 어떠한 값이 변경 되었을 때 리렌더링을 유발하고 해당 값을 반영하는 것이 필요하다

useState Hook

javascript
import { useState } from "react";

export function Counter() {
	const [count, setCount] = useState(0);
	
	function increaseCount() {
		setCount(count + 1);
		console.log(count);
	}
	
	function decreaseCount() {
		setCount(count - 1);
		console.log(count);
	}
	return (
	<div>
		<button onClick={increaseCount()}>1 더하기</button>
		<button onClick={decreaseCount()}>1 빼기</button>
		<p>점수 : {count}</p>
	</div>
	
}
  • useState 훅을 통해 카운트가 정상 작동 되는 것을 확인할 수 있다.

State의 속성

  • state는 자신이 속한 컴포넌트에 종속적이다. 이는 동일한 컴포넌트를 렌더링 하더라도 종속되어 있는 state 는 서로 독립적으로 작동한다는 의미이다.

    javascript
    import Counter from "./Counter";
    
    function App() {
    	return (
    		<div>
    			<Counter />
    			<Counter />
    		</div>
    	)
    
    }
    
  • Counter 컴포넌트를 두 번 렌더링하고 버튼을 클릭해보면 각각 다르게 카운팅 되는 것을 확인할 수 있다.

  • state 는 자신이 속한 컴포넌트에 독립적으로 관리되며, Counter 컴포넌트를 렌더링하는 부모 컴포넌트(App) 에도 Counter의 state 가 어떻게 작동하는 지 알 수없다.

  • 이때 부모 컴포넌트의 state 가 변경 되었을 때 사용하는 것이 props 혹은 상태 관리 기법이다. (Context API , recoil …)

State 업데이트

  • state 값이 변경되었을 경우 React에는 해당 컴포넌트를 리렌더링 하는 걸 확인할 수 있다. 이때 React는 불필요한 리렌더링을 방지하기 위해 state 를 변경하는 작업을 일괄적으로 처리하게 된다.
  • 이를 Batching 이라고 하며, 이를 통해 불필요한 리 렌더링을 어느정도 방지할 수 있다.
  • 또, 이 작업을 통해 컴포넌트 내부의 일부 state update 작업이 실행되지 않은 상태로 리 렌더링이 진행되는 half-finished 상태를 방지할 수 있다.
javascript
function changeState() {
	const [flag, setFlag] = useState(false);
	
	setFlag((prevFrag) => !prevFlag);
	setFlag((pervFlag) => !prevFlag);
	setFlag((pervFlag) => !prevFlag);
}

State === snapshot

  • 반환되는 JSX는 컴포넌트가 렌더링 된 순간의 스냅샷 이다.
  • React는 컴포넌트 내부의 props, event handler, 지역 변수를 렌더링 된 순간의 state 를 활용하여 계산하고 이를 반영하게 된다.
  • state 는 컴포넌트 외부에서 Closure 형태로 관리되는 변수로, React는 컴포넌트 함수가 호출된 순간의 state 값을 제공하며 이는 다음 렌더링 까지 변하지 않는다.
javascript
import {useState} from "react";

export function Counter() {
	const [count, setCount] = useState(0);
	
	function increaseCount() {
		setCount(count + 1);
		setCount(count + 1);
		setCount(count + 1);
	}
	
	return (
		<div>
			<button onClick = {increaseCount}>3 더하기</button>
			<p>점수 : {count}</p> 
		</div>
	)
}
  • 해당 코드를 실행하고 버튼을 클릭하게 되면 우리는 3의 값을 기대하지만 실제 결과는 1이 나오게 되는데 그 이유가 Batching 에 의해 마지막 부분만 적용하여 Count 값이 1이 나오게 되는 것이다.

태그

#React