자바스크립트는 일반으로 코드를 작성하면 synchronous 하게 처리된다. 코드를 적은 순서 그대로 위에서부터 아래로 코드가 실행된다는 뜻이다.
그런데 어떤 코드들은 synchronous 하지 않게 실행되는 코드들이 있다.
ajax, 이벤트 리스너, setTimeout 이런 함수들을 쓸 때 asynchronous, 즉 비동기적으로 코드가 실행된다.
이런 함수들은 보통 처리시간이 길다. ajax 로 예를 들면 인터넷 상황이 안 좋으면 코드 실행이 오래걸리는 것을 생각하면 된다.
그래서 이런 코드들은 순차적으로 실행되지 않고 완료되면 실행이 된다.
아래 코드를 실행시키면 2 4 가 순서대로 출력되고, 그 다음에 3이 출력된다. 이는 3을 출력하는 코드가 asynchronous 처리를 지원하는 코드이기 때문이다. 3을 출력할 때 오래걸리면 완료될 때까지 잠깐 보류했다가 다른 코드를 먼저 실행시킨다. 심지어 ajax 요청이 0.00 초 걸려도 2 4 가 먼저, 그 다음에 3이 출력된다. 물리적으로 처리가 잠깐 보류되어서 그렇다.
이런 비동기적인 코드 실행은 자바스크립트의 특징이자 장점이라고 볼 수 있다.
console.log(1+1)
axios로 get요청하고나서 console.log(1+2) 실행하기
console.log(1+3)
리액트 setState 함수 특징
function App(){
let [name, setName] = useState('kim')
}
리액트에서 state 를 사용할 때는 위 코드처럼 사용을 한다. 그리고 setName 을 사용해 name 이라는 state 를 자유롭게 변경 가능하다.문제는 setName 같은 state 변경함수들은 전부 asynchronous 하게 처리된다는 것이다. setName 이 오래걸리면, 제껴두고 밑에 있는 다른 코드부터 실행을 하기 때문에 예상치 못한 상황이 생길 가능성이 있다.
예제: 버튼을 누르면 2개의 기능을 순차적으로 실행하고 싶다
function App(){
let [count, setCount] = useState(0);
let [age, setAge] = useState(20);
return (
<div>
<div>{age}살</div>
<button>누르면한살먹기</button>
</div>
)
}
위와 같은 코드가 있을 때,
(1) count 라는 state 를 +1 해야함 (버튼 누른 횟수 기록용)
(2) age 라는 state 도 +1 해야함
(3) 근데 count 가 3 이상이면 더 이상 age 라는 state 에 1을 더하지 않는다 -> 22 살에서 멈춰야 함
function App(){
let [count, setCount] = useState(0);
let [age, setAge] = useState(20);
return (
<div>
<div>{age}살</div>
<button onClick={()=>{
setCount(count+1);
if (count < 3) {
setAge(age+1);
}
}}
>누르면한살먹기</button>
</div>
)
일단 이렇게 코드를 짜봤는데, 잘 동작하는 것 같지만 뭔가 이상하다. age 가 22 가 아니라 23 까지 증가한다.
count 가 2일때까지만 age 를 증가시켜주라고 코드를 짰는데, count 가 3 일 때도 age + 1 이 동작하고 있는 것 같다.
왜 이상하게 동작을 하는 것일까?
-> state 변경함수가 async 하게 처리되는 함수이기 때문!
state 변경함수가 비동기적으로 처리되기 때문에 완료되기까지 시간이 오래걸리면 제쳐두고 다음 코드를 실행시켜준다.
그래서 코드를 자세하게 뜯어보면, 아래와 같이 동작한다.
1. 버튼을 3 번째로 눌렀을 때 setCount(count+1); 을 실행해서 count 를 3 으로 만드려고 함
2. 근데 count 를 3으로 만드는 것이 오래 걸리니 제쳐두고 if (count > 3) { ... } 을 실행
3. 이 때 count 는 아직 2 라서 if 문 안의 setAge(age+1) 이 잘 동작
결국 이 문제는 state 변경함수인 setCount 가 async 함수라서 그런 것이다. 그래서 저렇게 state1 을 변경하고 나서 state 2 를 변경하는 코드를 작성할 땐 가끔 문제가 생긴다. 이걸 syncronous 하게 실행하고 싶을 때 해결책은 useEffect 를 사용하는 것이다.
useEffect 를 사용해서 코드를 작성해보았다. 이번에는 원래 원하던 바와같이 count 가 3 보다 작을 때만 setAge 가 동작해서 22살까지만 age 가 증가한다.
useEffect 로 count 값이 바뀔 때마다 useEffect 안에 작성되어 있는 코드가 실행되도록 코드를 짰다.
count !== 0 이라는 조건을 꼭 넣어줘야 올바르게 동작을 하는데, useEffect 는 컴포넌트가 최초로 렌더링 될 때도 실행되기 때문에count 가 0 인 상태에서도 age 가 증가하게 된다. 그래서 count !== 0 이라는 조건을 걸어주어야 불필요한 age 증가를 방지할 수 있다.
function App(){
let [count, setCount] = useState(0);
let [age, setAge] = useState(20);
useEffect(()=>{
if (count !== 0 && count < 3) { // count가 0 이 아니고, count가 3보다 작을 때
setAge(age+1);
}
}, [count])
return (
<div>
<div>{age}살</div>
<button onClick={()=>{
setCount(count+1);
}}
>누르면한살먹기</button>
</div>
)
}
'웹 > 24-StudyWithPnP' 카테고리의 다른 글
[React.js] 3주차 - React.js 입문(1) (0) | 2024.10.14 |
---|---|
[React.js] 1주차 - Node.js, React.js (1) | 2024.10.07 |
[React+JS/리액트] 웹 스터디 11주차 (0) | 2024.07.12 |
[React+JS/리액트] 웹 스터디 10주차 (0) | 2024.07.11 |
[React+JS/리액트] 웹 스터디 9주차 (0) | 2024.07.04 |