개발하고 싶은 초심자
[React] useState는 비동기인가 동기인가 본문
[React] useState는 비동기인가 동기인가
정새얀 2022. 12. 20. 20:59useState는 비동기인가 동기인가. 이런 주제를 왜 생각하게 되었냐면, api 요청을 patch로 하면서 상태를 변경하게 되었는데, 내가 생각한 로직대로 작성하면 제대로 상태가 변경되지 않은 채로 서버에 변경 요청이 가지 않았다.
그래서 내가 생각한대로 상태 변경이 되려면 어떻게 해야할까 생각하며 구글링을 해보다가, useState가 비동기인가 동기인가 라는 흥미로운 주제를 보게 되었다. 그래서 그 부분에 대한 내용을 찾기 시작했고, 정리한 내용을 블로그에 정리해보게 되었다.
결론부터 말하자면 useState는 비동기로 동작한다. 정확하게는, setState가 비동기로 동작한다.
✸ setState는 React에서 사용하는 비동기 함수로, 개발자들이 어플리케이션 상태를 변경할 때 매우 유용합니다.
비동기 프로세스를 통해 렌더링을 할 때 간단하고 효율적으로 상태를 변경할 수 있습니다.
setState는 다른 컴포넌트에서 사용되거나, 비동기 작업이 완료되거나, 사용자의 입력이 발생할 때 호출됩니다.
이러한 일이 발생하면 React가 렌더링 작업을 시작하며, 상태가 변경될 때마다 렌더링이 다시 일어납니다.
상태 변경이 이루어질 때 사용자는 이를 관찰할 수 있으며, 각 렌더링 단계에서 상태가 어떻게 변경되었는지 알 수 있습니다.
렌더링 단계마다 상태 변경이 이루어지면, 사용자는 다른 컴포넌트의 동작이 이루어지는 방식을 관찰할 수 있습니다.
마지막으로, setState는 React 어플리케이션의 상태를 일관되고 안정적으로 변경하는 데 매우 중요합니다.
(노션 ai assist 늘려쓰기 기능을 활용하여 setState의 비동기를 늘려써보았는데, 생각보다 엄청 내용이 상세하고 설명이 잘 되어있어 블로그에 가져와봤다)
setState가 비동기로 동작하는 이유는, 리액트가 효율적으로 렌더링하기 위해 여러 개의 상태값 변경 요청을 batch(일괄 처리/배치)처리하기 때문이다.
하나의 페이지나 컴포넌트 내에도 수많은 상태값이 존재하는데, 만약 리렌더링을 발생하는 setState가 일어날 때마다 리렌더링이 일어난다면 성능 이슈가 생길 수 있다.
그렇기 때문에 아무리 많은 setState가 연속적으로 사용되었어도 batch 처리에 의해 한 번의 렌더링으로 최신 상태를 유지한다.
✸ batch(일괄 처리): React가 너 나은 성능을 위해 여러개의 state 업데이트를 하나의 리렌더링으로 묶는 것.
React는 16ms 동안 변경된 상태 값들을 하나로 묶는다(16ms 단위로 배치를 진행한다).
setState가 비동기로 동작한다는 것을 알았다. 그렇다면 동기적으로 동작하게 하려면 어떻게 할 수 있을까?
① setState의 인자로 함수를 집어넣으면 동기적으로 동작한다(setState내 함수의 매개변수로 이전 상태가 들어온다).
② useEffect()의 종속성 배열을 활용한다.
인데...사실 종속성 배열을 사용하여, 콘솔 로그를 찍었을 때 해당 콘솔의 내용이 제대로 나오지 않았다. 그래서 이 부분은 사실상 구글링을 통해 알아낸 방법이다. 종속성 배열을 사용했을 때 왜 동기적으로 동작하는 지에 대해서는 더 알아볼 부분인 것 같다.
①번의 방법을 사용했을 때, 일반적인 경우 해당이 되는 것 같다.
하지만 나의 경우 patch api 요청을 했을 때, 함수 형태로 전달했을 때 제대로 서버까지 변경된 데이터로 들어가지 않았다.
import React, { useState } from 'react';
import axios from 'axios';
const [state, setState] = useState(false); // 초기값을 boolean
const handleChangeFunction = async() => {
try {
await axios.patch(`url`, {
thing: state
});
setState(state);
} catch(err) {
console.log(err);
}
}
원래 작성했던 코드는 이런 형식이었는데, 이렇게 작성하면 비동기적으로 작동한다.
import React, { useState } from 'react';
import axios from 'axios';
const [state, setState] = useState(false); // 초기값을 boolean
const handleChangeFunction = async() => {
try {
await axios.patch(`url`, {
thing: state
});
setState((state) => !state);
} catch(err) {
console.log(err);
}
}
이렇게 변경해주었다. 함수 형태로 작성하고, ! 연산자를 활용하여 상태를 변경하는 것이다.
하지만 첫 번째와 두 번째 코드에는 state, 즉 초기값 false인 상태가 그대로 patch 요청 안에 들어가있기 때문에 setState()안에 state를 넣어도 변경되지 않는다.
import React, { useState } from 'react';
import axios from 'axios';
const [state, setState] = useState(true); // 초기값을 false -> true
const handleChangeFunction = async() => {
try {
await axios.patch(`url`, {
thing: true
});
setState(true);
} catch(err) {
console.log(err);
}
}
임시방편으로 초기값을 true로 작성해두고, 아예 true로 바뀌도록 작성해두었다.
애초에 내가 원했던 방향은 false -> true로 상태가 변경되는 것이었기 때문이다.
하지만 궁극적으로 원하는 그림이 아니기 때문에 꽤 많이 찝찝하다.
+) 글을 작성하다 든 의문점: patch 요청을 보내는 것 자체가 수정을 요청하는 것인데, 왜 setState를 작성하는 것으로 바뀌지 않을까? 비동기로 작동하더라도, 함수형태로 변경하여 넣어주었을 때는 동기적으로 동작할 것이기 때문에 상태가 바뀌어야하지 않나?
'기술개념정리(in Javascript) > 개발&에러핸들링(in Work(Codestates))' 카테고리의 다른 글
[DOM] 자식요소 중 일부를 제외하고 삭제하는 방법 (0) | 2023.01.09 |
---|---|
[HTTP Method] PUT vs PATCH (0) | 2022.12.21 |
[React Error]Uncaught TypeError: Cannot read properties of undefined (reading 'map') (0) | 2022.12.14 |
zsh: command not found: nvm 오류 해결책 (1) | 2022.12.09 |
[React] 절대경로와 상대경로 (0) | 2022.12.04 |