📜
23년 5월 3일 흑우집합소 개발노트 (React에서 useState의 상태 처리)
2023.05.04
React에서 상태 관련 처리를 하다가…
신규 기능 생성번호 당첨내역을 개발하고 있었다.
백엔드 로직 개발을 하고, 프론트쪽 개발로 넘어왔다.
각 로또 등위별 당첨 내역 처리를 위해 아래와 같은 상태 값을 사용했다.
const [rankInfo, setRankInfo] = useState<RankSummary>({
firstRankCnt: 0,
secondRankCnt: 0,
thirdRankCnt: 0,
fourthRankCnt: 0,
fifthRankCnt: 0,
});
위 상태 값은 아래의 등위별 당첨 내역의 카운트에 쓰인다.
저 등위별 당첨 내역은 컴포넌트로 따서 구현되어 있다.
컴포넌트에서는 useEffect hook을 이용해서 초기 값을 설정해준다.
useEffect(() => {
const makeLogData = winData.lottoMakeLogData;
setRankInfo({
firstRankCnt: 0,
secondRankCnt: 0,
thirdRankCnt: 0,
fourthRankCnt: 0,
fifthRankCnt: 0,
});
makeLogData.forEach((item) => {
if (item.rank === 5) {
setRankInfo({
...rankInfo,
...{ fifthRankCnt: rankInfo.fifthRankCnt++ },
});
} else if (item.rank === 4) {
setRankInfo({
...rankInfo,
...{ fourthRankCnt: rankInfo.fourthRankCnt++ },
});
} else if (item.rank === 3) {
setRankInfo({
...rankInfo,
...{ thirdRankCnt: rankInfo.thirdRankCnt++ },
});
} else if (item.rank === 2) {
setRankInfo({
...rankInfo,
...{ secondRankCnt: rankInfo.secondRankCnt++ },
});
} else if (item.rank === 1) {
setRankInfo({
...rankInfo,
...{ firstRankCnt: rankInfo.firstRankCnt++ },
});
}
});
setRankInfo(updatedRankInfo);
}, [winData]);
근데 이렇게 했더니 계속 값이 증분했다.
앞에 초기화 로직을 줬지만 적용되지는 않았다.
왜 그런걸까?
이 부분을 찾아보니…
아래와 같이 정리할 수 있었다.
useState hook은 비동기로 동작하기 때문에 setRankInfo가 호출되어도 rankInfo는 즉각적으로 업데이트 되지 않는다.
그래서 이를 해결하려면 이전상태를 복사한 값을 적용함으로써 해결할 수 있다.
말이 좀 어려운데 아래 솔루션 코드를 보면 알 수 있다.
useEffect(() => {
const makeLogData = winData.lottoMakeLogData;
// 새로운 객체를 생성하여 상태 업데이트를 수행합니다.
const updatedRankInfo = {
firstRankCnt: 0,
secondRankCnt: 0,
thirdRankCnt: 0,
fourthRankCnt: 0,
fifthRankCnt: 0,
};
makeLogData.forEach((item) => {
if (item.rank === 5) {
updatedRankInfo.fifthRankCnt = updatedRankInfo.fifthRankCnt + 1;
} else if (item.rank === 4) {
updatedRankInfo.fourthRankCnt = updatedRankInfo.fourthRankCnt + 1;
} else if (item.rank === 3) {
updatedRankInfo.thirdRankCnt = updatedRankInfo.thirdRankCnt + 1;
} else if (item.rank === 2) {
updatedRankInfo.secondRankCnt = updatedRankInfo.secondRankCnt + 1;
} else if (item.rank === 1) {
updatedRankInfo.firstRankCnt = updatedRankInfo.firstRankCnt + 1;
}
});
setRankInfo(updatedRankInfo);
}, [winData]);
위와 같이 새로운 객체를 주고 해당 값으로 증가를 해준 다음 해당 값으로 setRankInfo를 보내주면 해결이 된다.
정리
useState, useEffect 함수는 비동기임을 잘 알고 써야할 것 같다.
그나저나 백엔드, 프론트엔드 둘다 왔다갔다 하니 약간 햇갈리기도 한다.
일할때는 역시 정신 똑바로 차리고 해야 할듯…
작은 개인광고 양해 바랍니다 ^^;;
👇 주인장이 직접 만든 서비스 👇
Dart
Flutter
hive
provider
마와셀(엡) - 와인과 셀러 관리, 시음노트
보유한 와인의 관리, 시음노트 작성, 보유 와인 셀러의 관리 어플리케이션