준영이의 성장일기(FrontEnd)
전역으로 데이터를 관리해야하는 경우는?(2) 본문
이전에 작성한 전역으로 데이터를 관리해야하는 경우는? 글에 이어서 내가 프로젝트에서 적용한 부분을 정리하고자 한다. 할인추가를 진행하는 API와 통신하고 추가된 할인정보 데이터를 받아오는 로직인데 기존의 로직은 다음과 같았다.
<기존의 로직>
✅ 가게에서 진행했던 할인행사 정보를 가져오는 로직인데 통신이 성공적으로 완료됐으면 진행했던 할인행사 정보를 setState()를 활용해 discountEvents라는 배열에 업데이트 해주었다.
Store 폴더에는 할인행사 정보를 관리하는 discountEventStore가 존재한다. 그 중 discountEvents는 가게의 할인행사정보들이 배열로 담겨있다. discountEvents는 할인행사가 추가될 때 하나씩 추가되어 업데이트 되는데 만약 진행했던 행사 정보를 가져와서 discountEvents에 업데이트 해주면 어떻게 될까?
A. 이때 할인정보에는 과거에 진행했던 할인정보 뿐만 아니라 방금 추가한 할인정보도 담겨있을 것이다. 이렇게 되면 진행했던 할인행사 페이지에서 discountEvents 값을 불러올 경우 과거에 진행했던 행사 뿐만 아니라 현재 진행중인 할인행사 정보도 같이 전역적으로 관리되기 때문에 의도한대로 상태를 관리할 수 없다.
A2. 이처럼 전역적으로 공유할 데이터인지 아닌지를 판단하는 것이 중요했고 판단 결과 진행했던 할인행사 페이지에서 사용할 할인행사 정보들은 API호출을 통해 받아온 데이터들을 useState를 사용하여 discountRecordPage에서 독립적으로 관리하자 라는 결론에 도달했다.
import axios from 'axios'
import discountEventStore, { DiscountEvent } from '@stores/discountEventStore'
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL
//미리 작성해둔 진행했던 할인 행사 페이지 api 로직
export const fetchDiscountEvents = async (storeId: number) => {
try {
const response = await axios.get(
`${API_BASE_URL}/v1/stores/${storeId}/discounts`,
)
console.log(response.data)
if (response.data.isSuccess) {
const fetchedDiscountEvents: DiscountEvent[] =
response.data.result.getDiscountDataDtoList.map(
(item: DiscountEvent) => ({
discountId: item.discountId,
storeName: item.storeName,
startDate: item.startDate,
endDate: item.endDate,
discountTitle: item.discountTitle,
//discounts: [], // 필요에 따라 실제 할인 항목을 여기에 추가
}),
)
discountEventStore.setState({
//데이터 잘 받아왔으면 스토어에 업데이트
discountEvents: fetchedDiscountEvents,
})
} else {
console.error('Failed to fetch discount events:', response.data.message)
}
} catch (error) {
console.error('Error fetching discount events:', error)
}
}
<수정한 로직>
A.에 작성한 대로 이와 같은 문제를 해결하고자 진행했던 할인행사 페이지에서 과거에 진행한 할인행사 정보를 가져온 뒤 useState를 사용하여 discountRecordPage.tsx에서 상태를 독립적으로 관리하도록 리팩토링 하였다.
✅ 이전과 다르게 setState()를 통해 discountEvent를 업데이트 해주는게 아니라 API 호출이 성공하여 반환된 데이터를 return 하는 형식으로 바꾸었다.
import axios from 'axios'
import discountEventStore, { DiscountEvent } from '@stores/discountEventStore'
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL
//미리 작성해둔 진행했던 할인 행사 페이지 api 로직
export const fetchDiscountEvents = async (storeId: number) => {
try {
const response = await axios.get(
`${API_BASE_URL}/v1/stores/${storeId}/discounts`,
)
console.log(response.data)
if (response.data.isSuccess) {
const fetchedDiscountEvents: DiscountEvent[] =
response.data.result.getDiscountDataDtoList.map(
(item: DiscountEvent) => ({
discountId: item.discountId,
storeName: item.storeName,
startDate: item.startDate,
endDate: item.endDate,
discountTitle: item.discountTitle,
//discounts: [], // 필요에 따라 실제 할인 항목을 여기에 추가
}),
)
return fetchedDiscountEvents
} else {
console.error('Failed to fetch discount events:', response.data.message)
}
} catch (error) {
console.error('Error fetching discount events:', error)
}
}
✅ loadDiscountEvents()를 호출하여 진행했던 할인행사의 정보를 가져온다. 이후 정보들이 있다면 setPastDiscountEvents를 활용하여 useState의 pastDiscountEvents를 업데이트 해준다. 업데이트 된 이후에는 pastDiscountEvents와 map을 이용하여 렌더링 해주도록 구현하였다. 만약 호출한 반환값이 없다면 진행했던 할인행사 정보가 없습니다 라는 컴포넌트(EmptyState)가 렌더링된다.
- discountRecordPage.tsx -
const [pastDiscountEvents, setPastDiscountEvents] = useState<DiscountEvent[]>(
[],
)
useEffect(() => {
async function loadDiscountEvents() {
if (storeInfos.length && storeInfos[0].id) {
const events = await fetchDiscountEvents(storeInfos[0].id)
// 가져온 이벤트를 상태에 저장
if (events) {
setPastDiscountEvents(events)
} else {
setPastDiscountEvents([]) // 기본값으로 빈 배열 설정
}
}
}
loadDiscountEvents()
}, [storeInfos])
return (
<PageContainer events={pastDiscountEvents.length > 0 ? 'true' : 'false'}>
<HeaderTitle
title="진행했던 할인행사 보기"
icon="back"
onClick={() => navigate('/manager')}
/>
{pastDiscountEvents.length > 0 ? (
<EventList>
{pastDiscountEvents.map((event) => (
<EventItem key={event.discountId}>
<EventTitle>{event.storeName}</EventTitle>
<EventDescription>{event.discountTitle}</EventDescription>
<EventPeriod>
{event.startDate} ~ {event.endDate}
</EventPeriod>
<DeleteButton onClick={() => handleDeleteClick(event.discountId)}>
삭제
</DeleteButton>
</EventItem>
))}
</EventList>
) : (
<EmptyState />
)}
</PageContainer>
)
깃허브 커밋내역은 다음과 같다.
https://github.com/UMC-6th-BAB/BAB-FE/pull/38/commits/e120a5862860ad1118d497f208b340b4a69d37b3
(#27)feat/discount register api by Jayjunyoung · Pull Request #38 · UMC-6th-BAB/BAB-FE
📢 기능 설명 코드 리뷰 환영합니다 ㅎㅎ ✨ 로직 쪽으로 수정해야할 부분 있으면 수정하겠습니다. (현재 가게는 store_id 1인 가게를 기준으로 API연동 하였습니다. 가게 등록이 연동되고 스토어
github.com
이전 내용
https://no2jfamily.tistory.com/80
전역으로 데이터를 관리해야하는 경우는?
최근 프로젝트를 하면서 전역으로 데이터를 관리하기 위해 Zustand와 같은 전역 상태관리 라이브러리를 사용하고 있다.그래서 컴포넌트간의 데이터 공유와 상태 관리를 보다 효율적으로 처리하
no2jfamily.tistory.com
'프론트엔드 > 상태관리' 카테고리의 다른 글
전역으로 데이터를 관리해야하는 경우는? (0) | 2024.08.14 |
---|---|
Zustand - get() vs getState() (0) | 2024.08.01 |