일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 개발
- 브라우저 렌더링
- routing
- Redux
- 비동기
- route
- setstate
- react
- 채팅방
- rendering
- qwe
- useEffect
- 항해99
- Preview
- CI/CD
- previousState
- 배포
- 동기
- updater
- Github Actions
- 후기
- 접근 제한 라우팅
- 7기
- 스파르타코딩클럽
- FileReader
- S3
- 미리보기
- imagePreview
- 라우팅
- socket.io
- Today
- Total
삐옹
[Teamnote] 하나의 스코프 안에서 setState 연속 사용 본문
문제
소속된 워크스페이스 목록을 조회하는 요청과 내가 받은 초대장 목록을 조회하는 요청(GET요청 x2)이
2개의 useEffect 안에서 실행되고 있다.
전역 state를 이용해 같은 slice의 다른 키 값으로 업데이트 요청을 보내는데
소속된 워크스페이스 목록의 값을 잘 불러왔다가,
또 어떤 때는 값이 들어왔다가 다시 초기값으로 돌아가는 상황.
Redux로 저장한 배열의 값이 여러번의 렌더링을 거친다.
초깃값 -> 업데이트 -> 초깃값 or 초깃값 -> 업데이트 패턴으로 리렌더링 할 때마다 들어오는 값이 달라짐
그래서 어떤 때는 배열 값이 비어있어서 에러가 뜨고 또 어떤 때는 잘 읽어온다.
예) 첫 렌더링 - arr = Array(0) / 두 번째 렌더링 - arr = Array(3 ) / 세 번째 렌더링 arr = Array(0) => Error
예2) 첫 렌더링 - arr = Array(0) / arr = Array(3) => Success
원하는 결과
화면이 렌더링 된 뒤 소속된 워크스페이스 목록도 초대장 목록의 값도 잘 받아오기
접근
콘솔을 보니 분명 어딘가에서 state를 업데이트를 시킬 때 동시에 업데이트가 진행되면서 실행이 꼬여 무작위적으로 값이 업데이트 되는 것으로 예상했다.
아무리 뒤져봐도 dispatch 해주는 부분에서 업데이트를 실수로 초기화 시켰다거나 그런 부분은 안 보이는데..
문제의 코드
// 소속된 워크스페이스 전체 목록 조회
useEffect(() => {
try {
axios
.get("http://43.200.170.45/api/members/spaceLists", {
headers: {
Authorization: `Bearer ${getItemFromLs("myToken")}`,
},
})
.then((res) => {
if (res.data.success) {
const wsInfoList = res.data.includedList;
const workSpaceFullname = wsInfoList.map((ws) => {
return ws.workSpace;
});
if (wsInfoList.length === 0) {
setAppState(APP_USER_STATE.NEWBIE);
setOpenNewbieModal(true);
} else {
setAppState(APP_USER_STATE.USER);
}
dispatch(
getUserInfo({
...user,
workSpaceList: [...workSpaceFullname],
}) // point(1)
);
}
});
} catch {
alert(" 불러오는 도중 에러가 발생했습니다 :(");
}
}, []);
// 본인에게 온 초대 여부 조회
useEffect(() => {
axios
.get(`http://43.200.170.45/api/members/inviting`, {
headers: {
Authorization: `Bearer ${getItemFromLs("myToken")}`,
},
})
.then((res) => {
console.log("res: ", res);
if (res.data.success) {
dispatch(
getUserInfo({
...user,
invitation: [...res.data.result],
}) // point(2)
);
}
})
.catch((err) => console.log(err));
}, []);
불변성도 잘 지키면서 redux값을 업데이트 시켰는데 어디서 초기화를 시켜주는거지?
아무리 봐도 주석으로 처리해둔 point 부분말고는 의심할만한 곳이 없다.
그래서 두 axios를 합쳐서 dispatch를 하나로 묶어 업데이트 해주었더니
해결되었다.
해결한 코드
// 소속된 워크스페이스 전체 조회
useEffect(() => {
try {
axios
.get("http://43.200.170.45/api/members/spaceLists", {
headers: {
Authorization: `Bearer ${getItemFromLs("myToken")}`,
},
})
.then((res) => {
console.log("res: ", res);
if (res.data.success) {
const wsInfoList = res.data.includedList;
console.log("wsInfoList: ", wsInfoList);
const workSpaceFullname = wsInfoList.map((ws) => {
return ws.workSpace;
});
if (wsInfoList.length === 0) {
setAppState(APP_USER_STATE.NEWBIE);
setOpenNewbieModal(true);
} else {
setAppState(APP_USER_STATE.USER);
}
axios
.get(`http://43.200.170.45/api/members/inviting`, {
headers: {
Authorization: `Bearer ${getItemFromLs("myToken")}`,
},
})
.then((res) => {
console.log("res: ", res);
if (res.data.success) {
dispatch(
getUserInfo({
workSpaceList: [...workSpaceFullname],
invitation: [...res.data.result],
})
);
}
})
.catch((err) => console.log(err));
}
});
} catch {
alert(" 불러오는 도중 에러가 발생했습니다 :(");
}
}, []);
한번 정리해보자.
컴포넌트가 렌더링 되면서 useEffect 2개가 동시에 실행이 된다.
게다가 그 안에서는 dispatch를 이용해 같은 slice의 다른 key값을 가진 state를 업데이트 시키고있다.
useEffect를 2번 호출했을 때 어떤 문제가 생기는 것인지 궁금해서 검색을 해보니

원래 React Hooks가 나오기 전에는 기본적으로
componentDidMount()나 componentDidUpdate()를 이용하여 side effect를 처리했는데
좀더 오류없이 유지보수도 쉽게 하기 좋도록 useEffect() 함수로 작성할 수 있게 되었다고 한다.
첫 렌더링 때 side effect를 중복해서 일으키므로 비동기 업데이트의 순서가 꼬여 업데이트 해야할 값들 다시 초깃값으로 돌려보낸 것 같다.
=> 질문방에 질문해보기
🙇🏻♂️참고한 블로그
[React] useEffect()와 Side-Effect
useEffect()? React에서 제공하는 useEffect()는 Side-Effect를 처리하기 위해 사용한다고 합니다. 그렇다면 Side-Effect는 무엇일까요? 의료계에서 말하는 부작용의 의미는 아니고, 컴퓨터 공학에서 사용하는
points.tistory.com
https://www.codeit.kr/community/threads/37594
코딩이 처음이라면, 코드잇
월 2만원대로 Python, JavaScript, HTML/CSS 등 2,600개 이상 프로그래밍 강의를 무제한 수강하세요
www.codeit.kr
'프로젝트' 카테고리의 다른 글
[Pomodoro]progress bar 기능을 하는 UI만들기 (0) | 2023.06.16 |
---|---|
[Pomodoro] 기능 별 프로세스 정리 (0) | 2023.06.16 |
[TeamNote]페이지 이동 구현하기_Trouble Shooting (0) | 2022.08.12 |
[Teamnote] LocalStorage의 값 변경 + 저장하기 (실패) (0) | 2022.07.25 |