이번에는 자바스크립트의 동기와 비동기 처리 방식에 대해 알아보고, 그 중에서도 리액트의 seetState 함수의 특징에 대해 알아보겠습니다.
1. 자바스크립트에서의 동기와 비동기 처리
자바스크립트는 기본적으로 코드를 동기적으로 처리합니다. 즉, 코드는 작성된 순서대로 한 줄씩 실행됩니다.
console.log(1+1)
console.log(1+2)
console.log(1+3)
위 예시 코드를 보면 한 줄씩 실행되어 2, 3, 4를 순차적으로 출력합니다. 이는 대부분의 프로그래밍 언어에서 동일하게 동작합니다.
하지만, 자바스크립트에서는 비동기적인 코드 실행도 가능합니다. 이는 특정 함수들이 처리 시간이 오래 걸릴 수 있는 경우에 주로 사용됩니다. 예를 들어 AJAX 요청이나 이벤트 리스너, setTimeout과 같은 함수들은 시간이 오래 걸리 수 있기 떄문에 코드의 실행을 보류한 채 다른 코드를 먼저 실행합니다.
console.log(1+1)
axios로 get요청하고나서 console.log(1+2) 실행해주셈~
console.log(1+3)
위와 같은 코드를 작성했을 때, 2,4가 출력이 되고 그 다음에 3이 출력됩니다.
2. 리액트의 setState 함수 특징
리액트에서는 state를 관리하기 위해 useState 훅을 사용합니다. useState를 통해 생성된 state 변경 함수를 사용하면 state를 변경하는 것이 가능합니다.
그러나 주의할 점은 state 변경 함수는 비동기적으로 당작한다는 것입니다. 즉, state 변경 함수가 호출되면 해당 state의 변경은 완료되기 전까지 제쳐두고 다음 코드를 실행합니다.
아래의 예시를 보면서 자세히 알아보겠습니다.
function App() {
const [count, setCount] = useState(0);
const [age, setAge] = useState(20);
return (
<div>
<div>안녕하십니까, 저는 {age}세입니다.</div>
<button onClick={() => {
setCount(count + 1);
if (count < 3) {
setAge(age + 1);
}
}}>누르면 한 살 먹기</button>
</div>
);
}
위 코드는 버튼을 누를 때, 첫 번째로 count state를 1씩 증가시키고 두 번째로 age state를 1씩 증가시킵니다. 그러나 count가 3 이상이라면 더 이상 age state를 변경하지 않도록 조건문을 추가했습니다. 즉, age는 22에서 멈추어야 합니다.
하지만 위 코드를 실행해보면 23까지 age가 증가하는 것을 확인할 수 있습니다. 이는 setCount 함수가 비동기적으로 동작하기 때문에 발생하는 문제입니다.
이럴 때 해결책으로는 useEffect를 확용하는 방법이 있습니다. useEffect는 컴포넌트가 렌더링 또는 재렌더링될 때 실행되는 함수입니다. 또한 useEffect의 두 번째 매개변수로 dependency array를 전달함으로써 특정 상태가 변경될 때만 실행되도록 설정할 수 있습니다.
따라서 위 코드에서 useEffect를 활용하여 count가 변경될 때에만 실행되도록 코드를 작성합니다.
1) 버튼을 눌렀을 때 count만 1이 증가하도록 수정합니다.
<button onClick={()=>{
setCount(count+1);
}}>누르면한살먹기</button>
2) age가 1씩 증가하는 코드는 useEffect안에 개발합니다.
useEffect(()=>{
if ( count < 3 ) {
setAge(age+1)
}
}, [count])
이렇게 하면 count가 변경되고 난 후에 age를 변경하도록 순차적으로 코드를 실행할 수 있습니다.
3) 첫 페이지 로드 시 일어날 수 있는 버그를 방지합니다.
useEffect는 초기 렌더링 시에도 한 번 실행되기 때문에 의도치 않은 버그가 발생할 수 있습니다. 이를 방지하기 위해서는 useEffect 내부에 조건문을 추가하여 초기 렌더링 시에는 코드를 실행하지 않도록 처리할 수 있습니다.
useEffect(() => {
if (count !== 0 && count < 3) {
setAge(age + 1);
}
}, [count]);
위와 같이 count가 0일 때에는 내부 코드를 실행하지 않도록 조건을 추가할 수 있습니다.
'React' 카테고리의 다른 글
React (Node+Express 서버와 react 연동) (1) | 2023.10.31 |
---|---|
React 쇼핑몰(Progressive Web App) (0) | 2023.10.31 |
React 쇼핑몰(Automatic Batching, useTransition, useDeferredValue) (1) | 2023.10.30 |
React 쇼핑몰(memo, useMemo) (1) | 2023.10.29 |
React 쇼핑몰(개발자도구, lazy import) (0) | 2023.10.29 |