과거에 state를 업데이트함에 있어 비동기적 속성을 언급한 적이 있습니다.
state가 바뀌면 재 렌더되고, 재 렌더된 후에 state가 바뀐 것을 확인할 수 있다는 내용이었습니다.
https://darrengwon.tistory.com/651
복잡해지니 단순히 state에 대해 정리하자면,
1. state가 바뀌면 해당 state를 사용하는 컴포넌트와 그 하위 자식 컴포넌트들은 재렌더링 된다.
=> 때문에 재렌더링을 최소화하기 위해 필요한 state에 따라 컴포넌트를 분리해야 한다
=> 대표적으로 삼항연산자, form, 반복문(map, filter...), redux에서 state를 받아 쓰는 부분 등
2. 재 렌더링 된 후에 state가 반영된 것을 확인할 수 있으므로 setState 직후 state를 확인할 수는 없다.
3. 객체 형태로 setState를 하면 오브젝트 컴포지션이 되어 덮어씌워져 원하는 동작을 하지 않을 수도 있다.
=> 함수형 업데이트가 필요한 이유이다.
여기서는 state를 바꾸는데 사용되는 setState의 작동방식에 대한 비동기성을 살펴보겠습니다.
함수형 컴포넌트에서 useState 훅을 사용하던 클래스형 컴포넌트에서 setState를 사용하던 state를 변화시키는 동작은 asynchronous, 비동기적입니다.
비동기적인 이유는 리액트가 여러번 setState를 만나게 되면 batching하여 state를 업데이트하기 때문입니다. 매번 호출 순서대로 바로 업데이트하지 않고 인자로 전달된 객체들을 하나로 합치는 작업을 합니다. 이런 과정은 '오브젝트 컴포지션' 이라고 합니다.
코드로 풀면 아래와 같다는 군요
이러한 비동기적인 방법을 해결하기 위해서는 setState에 값을 그대로 전달하는 것이 아니라 함수를 전달하면 됩니다. 이를 '함수형 업데이트'라고 합니다.
객체와 같은 형태가 아니라 함수이기 때문에 따로 오브젝트 컴포지션을 하지 않고 호출된 순서대로 큐에 넣고 큐에 넣어진 대로 함수를 실행합니다.
또, 이러한 함수형 업데이트를 진행할 때 함수는 컴포넌트 외부에 분리하는 것이 추후 테스트에 좋습니다.
이후 jest를 이용한 테스트에 관련된 포스트를 작성할 때 한 번 짚고 넘어가야 겠습니다.
// 비분리
function App() {
const [counter, setcounter] = useState(0);
const onClick = () => {
return setcounter((prev) => prev + 1);
};
return (
<div>
<div>count : {counter}</div>
<button onClick={onClick}>plus 1</button>
</div>
);
}
export default App;
// 분리. onClick 이벤트를 핸들링하는 함수 로직을 외부에 분리함.
function plusOne(prev) {
return prev + 1;
}
function App() {
const [counter, setcounter] = useState(0);
const onClick = () => {
return setcounter(plusOne);
};
return (
<div>
<div>count : {counter}</div>
<button onClick={onClick}>plus 1</button>
</div>
);
}
export default App;
참고한 글)
'React, Next, Redux > ⚛ React.JS' 카테고리의 다른 글
좋아요/싫어요 구현하기 (0) | 2020.09.17 |
---|---|
댓글과 무한 대댓글 컴포넌트 작성 및 로직 (0) | 2020.09.16 |
React 파일, 컴포넌트 관리를 위한 atomic design (0) | 2020.08.25 |
dangerouslySetInnerHTML : 문자열로 출력되는 html을 렌더링하기 (0) | 2020.07.26 |
react + multer-s3 이미지 전송 (0) | 2020.07.22 |