Skip to Content
Suffering builds character

5. useState

useState는 함수형 컴포넌트 내부에서 상태를 관리할 수 있게 제공해주는 hook으로, React에서 기본적으로 제공되는 하나의 내장 함수

1. useState 시그니처

const [state, setState] = useState(initialState);

1-1. 파라미터(Parameters)

초기 값으로 초기화할 값을 전달, JS의 어떤 타입이든 할당 가능

초기값은 페이지가 초기 렌더링 될 때만 수행되고 이후 컴포넌트가 다시 호출될 때는 초기값으로 재할당(assignment)되지 않음

Tip.
만약 초기값에 대한 초기화 로직이 다소 복잡할 경우에는 아래와 같이 useState의 인수로 값이 아닌 콜백 함수를 전달하여 콜백 함수 내부에 추가적인 로직을 작성할 수 있음

useState(() => { console.log('복잡한 초기화 로직'); // ... })

1-2. 반환 값(Return)

useState는 2개의 요소를 가진 배열을 반환

const [state, setState] = useState(0); console.log(useState(0)); // Array(2) [0, function]

1. 배열의 첫 번째 요소
현재 state에 초기화된 상태 값

2. 배열의 두 번째 요소
setter() 함수
state의 값을 새롭게 업데이트할 수 있도록 제공하는 함수

setter()의 인수에 전달한 값을 통해 state의 값을 업데이트할 수 있으며, setter()가 호출되면 re-rendering이 발생함

re-rendering
컴포넌트가 다시 호출되면서 페이지 내 일부 UI가 새롭게 렌더링 됨

2. useState를 사용하지 않았을 때

useState 없이 카운터를 구현할 경우, 다음과 같은 문제가 발생함

const Counter = () => { console.log('rendered'); let count = 0; const clickHandler = () => { console.log(`count: ${count}`); count += 1; } return ( <> <div>{count}</div> <button onClick={clickHandler}>click</button> </> ) } const root = ReactDOM.createRoot(document.getElementById('root')); root.render(<Counter />);
  1. Counter 컴포넌트가 페이지에 출력되기 위해 초기에 렌더링됨
    → Counter 컴포넌트 함수가 한 번 호출됨
root.render(<Counter />); // 'rendered'
  1. 이후 버튼이 클릭될 경우, count의 값이 증가함
console.log(`count: ${count}`); // count: 0 console.log(`count: ${count}`); // count: 1 console.log(`count: ${count}`); // count: 2 // ...
  1. 함수로 작성된 Counter 컴포넌트의 return 키워드를 통해 반환되는 결과값이 이전에 출력된 결과값과 비교하였을 때, 변경된 부분이 존재하지 않기 때문에 페이지에는 새롭게 업데이트된 값으로 출력되지 않게 됨

초기에 Counter 컴포넌트가 반환하여 페이지에 출력된 결과값

return ( <> <div>0</div> <button onClick={clickHandler}>click</button> </> )

버튼이 클릭된 후 Counter 컴포넌트가 반환한 결과값
→ 초기에 반환된 결과값과 동일**(변경된 부분이 없음)**

return ( <> <div>0</div> <button onClick={clickHandler}>click</button> </> )

3. useState에서 setter()만 사용하였을 때

Tip. setter(arg)
일반적으로 객체 지향에서 매개변수로 전달된 인수의 값을 수정할 때 사용되는 메서드(함수)를 가리킬 때 사용되는 표현

const { useState } = React; const Counter = () => { console.log('rendered'); const [, render] = useState(0); let count = 0; const clickHandler = () => { count += 1; console.log(`count: ${count}`); render(); } return ( <> <div>{count}</div> <button onClick={clickHandler}>click</button> </> ) }
  1. Counter 컴포넌트가 페이지에 출력되기 위해 초기에 렌더링됨
root.render(<Counter />); // 'rendered'
  1. 이후 버튼이 클릭될 경우, count의 값이 증가함
console.log(`count: ${count}`); // count: 1
  1. setter()render()가 호출되어 Counter 컴포넌트가 다시 호출됨
console.log('rendered'); // 'rendered' let count = 0; // count 값이 다시 0으로 초기화됨
  1. 결과적으로 return 키워드를 통해 반환되는 값은 이전 결과값과 동일하기 때문에 페이지가 다시 렌더링되지 않게됨
return ( <> <div>0</div> <button onClick={clickHandler}>click</button> </> )

4. useState에서 setter()state를 같이 사용하였을 때

const { useState } = React; const Counter = () => { console.log('rendered'); const [count, render] = useState(0); const clickHandler = () => { console.log(`count: ${count}`); render(count + 1); } return ( <> <div>{count}</div> <button onClick={clickHandler}>click</button> </> ) } const root = ReactDOM.createRoot(document.getElementById('root')); root.render(<Counter />);
  1. Counter 컴포넌트가 페이지에 출력되기 위해 초기에 렌더링됨
root.render(<Counter />); // 'rendered'
  1. 이후 버튼이 클릭될 경우, count의 값이 증가함
console.log(`count: ${count}`); // count: 1
  1. setter()render()가 호출되어 Counter 컴포넌트가 다시 호출됨
console.log('rendered'); // 'rendered'
  1. 함수로 작성된 Counter 컴포넌트의 return 키워드를 통해 반환되는 결과값이 이전에 출력된 결과값과 비교하였을 때 변경된 부분이 존재하기 때문에 페이지에는 새롭게 업데이트된 결과값으로 렌더링됨

초기에 Counter 컴포넌트가 반환하여 페이지에 출력된 결과값

return ( <> <div>0</div> <button onClick={clickHandler}>click</button> </> )

버튼이 클릭된 후 Counter 컴포넌트가 반환한 결과값
→ 초기에 반환된 결과값과 다름 (변경된 부분이 존재)

return ( <> <div>1</div> <!-- 변경된 부분(0 → 1) --> <button onClick={clickHandler}>click</button> </> )
Last updated on