React를 사용하면서 상태를 업데이트 할 때 쓰게되는 prevState
분명 react 초기에는 사용원리에 대해 알았지만 이제는 사용 의미를 알고 쓰기보단 무의식적으로 쓰게 되어 다시금 prevState를 왜 사용하는지에 대해 글로 정리해보고자 한다.
prev state 를 왜 사용하는지를 이해하려면 우선 setState()
가 정확히 어떤동작을 하는지에 대해 짚고 넘어가야 한다.
1) state
가 바뀌면 화면 전체가 자동으로 다시 그려진다. (리렌더링)
다시 공부하면서 알게 된 사실 :let은 값이 바뀌어도 다시 렌더링 하지 않는다
2)setState() 는 비동기로 작동한다
setStatae(updater [, callback])
setState(updater [, callback]) 의 콜백 함수가 실행된 후 리렌더링 된다.
updater: (state, props) = > stateChange
즉 한번에 여러개의 state를 사용해도 모든 함수의 실행이 종료 된 후에 리렌더링이 진행된다.
💡 Why?
setState
가 비동기가 아닌 동기로 작동하게 되면 변경될 때마다 바로바로 렌더링이 일어나 비효율적이기 때문이다.
위 성질을 이해한 뒤 아래 코드를 보겠습니다.
const [state, setState] = useState(0);
const sumAll1 = () => {
setState(state + 1);//0
setState(state + 2);
setState(state + 3);
setState(state + 4);
};
return (
<>
<div>결과는 : {state}</div>
<button type='button' onClick={sumAll1}>
실행1 !
</button>
</>
);
위 코드는 sumAll1 함수가 실행되었을때 값이 10이 되기를 기대하며 작성한 코드이다. 그렇지만 아래 실행 결과를 보면 10이 아닌 4가 출력된다.
위에서 설명했듯 변경된 값이 바로 반영되는 것이 아니고 임시 저장공간에 넣어두고, 함수가 끝나고 나서 한번만 일어나기 때문에 마지막에 호출된 setState(state + 4)만 반영되어 리렌더링이 진행된다.
이럴 때 prevState
를 사용하면 임시 저장공간에 있는 값을 받아올 수 있다
임시 저장공간에 값이 없으면 default 값을 가져온다.
(prevState) 의 네이밍은 자유롭다.
리렌더는 동일하게 함수가 종료되고 나서 한번만 일어난다.
const sumAll2 = () => {
setState((prev) => prev + 1);
setState((prev) => prev + 2);
setState((prev) => prev + 3);
setState((prev) => prev + 4);
return (
<>
<div>결과는 : {state}</div>
<button type='button' onClick={sumAll2}>
실행2 !
</button>
</>
};
이제 prev(이전) 값을 받아 모든 setState구문이 동작하게 되니 10이 정상적으로 출력되는 것을 볼 수 있다.
const [isOpen, setIsOpen] = useState(false);
const onToggleModal = () => {
setIsOpen((prev) => !prev);
};