본문 바로가기

TIL/기록

[TIL] React Hook - useState

useState Hook은 가장 기본적인 hook으로 함수형 컴포넌트 내에서 가변적인 상태를 갖게한다. 

 

const [state, setState] = useState(초기값)

 

원래는 useState가 return 하는 값이 배열이다. 그리고 그 배열을 구조분해할당으로 받은 것 뿐이다.

배열에 return 값은 초기값으로 지정해놓은 그 변수 state가 있고, 그 state를 변경할 수 있는 setState가 있다. 

 

 

 

함수형 업데이트가 왜 필요한가?

export default funtion App() {
	const [number, setNumber] = useState(0);
    
    return <div>Number state: {number}</div>;  //Number state: 0
}

 

 

여기에 만약 버튼을 누르면 +1씩 올라가는걸 구현하려고 했다면 어떻게 했어야했을까?

 

일반적으로 썼던 업데이트 방식으로 코드를 쳐보자.

 

export default funtion App() {
	const [number, setNumber] = useState(0);
    
    return (
    <>
    	<div>Number state: {number}</div>
        <button onClick={() => { setNumber(Number + 1); }}> 누르면 +1씩 증가</button>
    </>
    )
}

 

 

 

이렇게도 할 수 있지만 "함수형" 업데이트로 써줄 수 있다. 

 

함수를 넣을 수 있고, 인자는 현재 state를 가져오고, 메인 로직 부분에는 이 값을 변경하는 코드를 작성할 수 있다.

export default funtion App() {
	const [number, setNumber] = useState(0);
    
    return (
    <>
    	<div>Number state: {number}</div>
        
        // 값을 변경하는 코드를 작성
        <button onClick={(currentNumber) => { 
        	return currentNumber + 1;
        }}
        > 누르면 +1씩 증가</button>
    </>
    )
}

 

 

함수로 이렇게 쓴 로직이 위에 쓴 { setNumber(Number + 1); }   이 로직과 같다.

 

 

 

일반 업데이트 방식과 함수형 업데이트 방식의 차이점은 무엇일까?

 

 

 

Q) 만약 한번의 클릭에 onClick을 세번 호출한다고 가정했을 때!

 

export default funtion App() {
	const [number, setNumber] = useState(0);
    
    return (
    <>
    	<div>Number state: {number}</div>
        <button onClick={() => { 
        	//기존 업데이트 
        	setNumber(Number + 1); 
        	setNumber(Number + 1);
            	setNumber(Number + 1);
            
        }}> 누르면 +1씩 증가</button>
    </>
    )
}

 

 

여기서 우리가 생각했던 정답은 3이 나와야할 것이라고 가정했지만 1만 올라갔다.

 

여기서 렌더링을 하기 위해서 state를 파악을 하는데 여기서 기존 업데이트는 state를 파악하는 방법이 바로 "배치 업데이트"이다.

배치 업데이트 방식은 React가 한꺼번에 파악하고 모아서 한 번만 반영을 하기 때문에 

setNumber가 세번 호출이 되어도 똑같은게 있으니까 이걸 모아 한개로 친다.

그래서 setNumber를 몇백번 써도 1만 올라간다.

 

 

 

 

Q)  그렇다면 함수형 업데이트로는 어떨까??

 

export default funtion App() {
	const [number, setNumber] = useState(0);
    
    return (
    <>
    	<div>Number state: {number}</div>
        
        <button onClick={() => {
        	setNumber((currentNumber) => currentNumber + 1); 
                setNumber((currentNumber) => currentNumber + 1); 
                setNumber((currentNumber) => currentNumber + 1); 
        	}}	
         >
         누르면 UP
        </button>
    </>
    )
}

 

이 함수형 업데이트에서는 한번 누르면 3이 올라간다.

 

이유는 무엇일까? 함수형 업데이트는 명령들을 모아서 순차적으로 한번씩 실행하기 때문이다.

 

 

 

왜? 

 

여기서 currentNumber 인자 부분에는 현재 상태의 state가 들어오고 => 그 뒤에는 바뀐 state를 반환한다고 했다. 

그리고 그 다음줄에서는 바뀐 state를 현재 state로 받아오고, 다시 바뀐 state를 반환하고, 이런식으로해서 3번이 실행됐다.

그래서 이렇게하면 최신값들을 계속해서 유지할 수 있다.

 

 

 

 

그럼 왜 배치 업데이트가 되도록 설계했을까?

 

React에서는 렌더링이 너무 잦은건 성능에 이슈가 있다고 본다.

불필요한 렌더링을 피하기 위해 한꺼번에 모아서 한번만 처리하는게 렌더링을 줄일 수 있는 좋은 방법이라 React에서는 배치 업데이트를 사용했던 것이였다. 

웨이터는 불필요한 동선을 줄이기 위해 손님의 주문을 모두 듣고 주방에 한꺼번에 말해주러 가는 것처럼

React도 렌더링을 줄이는 방식으로 이렇게 쓰는 것이다. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'TIL > 기록' 카테고리의 다른 글

[TIL] useState와 useRef  (0) 2024.01.31
[TIL] hook - useContext  (1) 2024.01.30
[TIL] React에서 map, filter로 문제풀어보기  (0) 2024.01.27
[TIL] useState  (1) 2024.01.24
[TIL] React 기본 용어  (0) 2024.01.23