기록
React.js - setState 본문
참조: 리액트 공식문서, https://youtu.be/hSdVDBPTT0U
setState
"setState()는 컴포넌트의 state 객체에 대한 업데이트를 실행합니다.
state가 변경되면, 컴포넌트는 리렌더링됩니다."
예전 state 값으로 새로운 state를 만들 때, 즉 이전 값을 기반으로 다음 값을 바꿀 때는 함수를 사용하자.
함수를 사용하면 이전 값을 인자로 접근할 수 있기 때문이다.
리액트의 state는 객체라는 것은 이미 알고 있는 사실이다.
여기서 더 나아가 state의 내부 로직이 어떻게 동작하는지 정리해보려고 한다.
1. setState()는 비동기적으로 동작함.
2. setState()를 연속적으로 호출했을 때, 리액트 내부적으로 batch 처리를 함.
3. setState()에 state 객체를 넘겨줄 수 있고, 새로운 state를 반환하는 함수를 인자로 넘겨줄 수 있음.
관련 예시
import { useState } from 'react';
function App() {
const [num, setNum] = useState(0);
const addNum = () => setNum(num + 1);
const subractNum = () => setNum(num - 1);
const multiplyNum = () => setNum(num * 2);
const multyplyAndAdd = () => {
multiplyNum();
addNum();
};
return (
<>
<h1>Number: {num}</h1>
<button onClick={addNum}>+1</button>
<button onClick={subractNum}>-1</button>
<button onClick={multiplyNum}>*2</button>
<button onClick={multyplyAndAdd}>*2 + 1</button>
</>
);
}
export default App;
(잘못된 코드)
setState는 비동기적으로 동작한다. 실행되자마자 바로 state를 변경하고 바로 렌더링하는 것이 아님.
리액트는 state가 업데이트 되기 이전, 현재 state 값으로 만든 element tree 와
업데이트된 state 값으로 만든 element tree를 비교한 다음
최종적으로 변경된 부분이 있으면 그걸 DOM에 적용하는 과정을 거친다.
그래서 만일 setState가 연속적으로 호출되면 각 setState를 merging하고 setState는 한 번만 호출한다.
merging?
리액트에서 state는 기본적으로 객체이다.
state는 객체의 key로 들어가는 것이다.
const currState = { num: 0 } 이렇게 말이다.
여기서 예를 들어 setState(num + 1) 을 실행하면
Object.assign(currState, { num: num +1 });
이러한 동작으로 실행되는 것이다.
그래서 merging을 한다면?
const newState = Object.assign(currState, { num: num*2 }, { num: num+1 });
setNum(newState);
이렇게 3개의 객체를 합치게 되는 것이다.
그래서 합쳐진 새로운 객체를 setState해준다.
이렇게 merging.을 해서 setState를 한 번만 호출하는 것이다.
Object.assign은 동일한 키가 있으면 덮어씌우기 때문에 3개의 객체를 합치면 결국 가장 마지막 addNum만 적용된 것처럼 화면에 보이는 것.
그렇다면 해결 방법은?
setState는 기본적으로 이전의 state를 받고, 새로운 state를 반환하는 함수를 인자로 받을 수 있다.
그래서 setState 안에 들어가는 로직을 다음과 같이 수정하는 것이다.
const addNum = () => setNum((num) => num + 1);
const subractNum = () => setNum((num) => num - 1);
const multiplyNum = () => setNum((num) => num * 2);
그러면 우선 multiplyNum()을 실행하면 로직을 실행한 결과를 반환하고,
여기서 return 된 값을 다음 함수addNum의 인자로 넘겨주게 되는 것이다.
const multyplyAndAdd = () => {
multiplyNum();
addNum();
};
이렇게 수정하면 우리가 원하는대로 코드가 실행되는 것을 확인할 수 있다.
'React.js > etc' 카테고리의 다른 글
React cra 명령어 (0) | 2021.03.25 |
---|---|
코드스플리팅 (0) | 2021.03.17 |
formik (0) | 2021.03.16 |
react app polyfill core-js (0) | 2021.03.16 |
504 Gateway timeout HTTP 504 (0) | 2021.03.13 |