useState
- useState는 컴포넌트에서 State 값을 추가할 때 사용됩니다. 함수형 컴포넌트에서는 클래스형 컴포넌트처럼 State를 사용할 수 없기 때문에, Hook을 사용해서 State와 같은 기능을 수행할 수 있도록 만들어 주었습니다.
- 하나의 useState 함수는 하나의 상태 값만 관리할 수 있어 만약 컴포넌트에서 관리해야 할 상태가 여러 개라면 useState를 여러 번 사용해야합니다.
state 변경 시, setState를 쓰는 이유
- State는 컴포넌트 렌더링에 영향을 주는 데이터를 갖고 있는 객체입니다.
- 직접 State를 수정하면 리액트는 render 함수를 호출하지 않아서 렌더링이 일어나지 않고, setState를 호출하여 State가 변경되면 리액트 엔진이 render 함수를 이용해서 렌더링을 실행합니다.
- setState를 호출하면 기존 State와 setState로 설정된 값을 비교하여 값이 변경되었으면 render 함수를 호출합니다.
setState의 동작
- setState는 비동기적으로 동작합니다.
- 변경된 값들을 모아서 한번에 업데이트를 진행하여 렌더링을 줄이고자 배치(Batch) 기능을 사용해 비동기로 작동합니다.
- 배치 업데이트 주기 : 16ms
setState 동기적으로 처리하기
- setState에 updater 함수를 사용해 이전 State의 값을 참조 가능하도록 합니다.
- updater 함수 : state와 props를 인자로 받는 state를 변화시키는 함수
- setState((state, props)=>{...})에서 state와 props는 최신 상태로 보장됩니다.
import React, { useState } from 'react';
function App() {
const [data, setData] = useState(0);
return (
<div>
<button
onClick={() => {
setData(data + 1);
setData(data + 1);
setData(data + 1);
}}
>
잘못된 패턴: {data}
</button>
<button
onClick={() => {
setData((data) => data + 1);
setData((data) => data + 1);
setData((data) => data + 1);
}}
>
올바른 패턴: {data}
</button>
</div>
);
}
export default App;
setState로 state 변화가 완료된 이후 로직이 실행되도록 하는 방법
- setState에는 await 키워드를 사용할 수 없습니다.
- useEffect의 의존성 배열에 state를 넣고, useEffect 안에서 로직을 구현합니다.
- 초기 렌더링에서 useEffect가 동작하지 않도록 하기위해 useRef를 활용할 수 있습니다.
참고자료