67e71c23-e88f-41ba-bb74-0f0634338bed.MOV
페이지를 새로고침함으로서 발생하는 이벤트 중 하나인 beforeunload
를 활용하여 현재 선택된 데이터를 세션스토리지에 저장합니다.
function useSaveStateOnUnload(storageKey: string, stateToSave: InitialUIStateType) {
useEffect(() => {
const handleBeforeUnload = () => {
sessionStorage.setItem(storageKey, JSON.stringify(stateToSave))
}
window.addEventListener('beforeunload', handleBeforeUnload)
return () => {
window.removeEventListener('beforeunload', handleBeforeUnload)
}
}, [storageKey, stateToSave])
}
이후 API를 호출하여 데이터를 불러오고, 해당 데이터와 스토리지에 저장된 데이터를 비교합니다. 이 둘이 만약 다르다면, 사용자에게 데이터를 원복할건지 묻는 컨펌창을 띄우고, 수락시 스토리지에 저장된 데이터로 데이터를 원복합니다.
실제 API 요청 순서를 모사하기 위해 fetchOrderSheet
를 먼저 디스패치한 뒤, postPointsReward
를 디스패치합니다. 그 이유는 포인트 혜택에 대한 정보를 요청할 때 실제로는 주문서 정보를 가져온 뒤 그 안에 있는 아이템 id, 주문서 id 등을 활용하기 때문입니다.
useEffect(() => {
const initialize = async () => {
const storageData = loadStateFromSessionStorage(FORM_STATE_KEY);
if (!storageData) {
return
}
const orderSheetAction = await dispatch(fetchOrderSheet());
const pointsRewardAction = await dispatch(postPointsReward())
asyncThunk를 통해 불러온 비동기 데이터가 에러인지 아닌지 확인합니다. 만약 에러인 경우, 스토리지 값을 제거하고 경고창을 띄워 에러 발생을 알립니다.
const orderSheetPayload = orderSheetAction.payload
const pointsRewardPayload = pointsRewardAction.payload
if (
!orderSheetPayload ||
!pointsRewardPayload ||
checkErrorBaseType(orderSheetPayload) ||
checkErrorBaseType(pointsRewardPayload)
) {
removeStateFromSessionStorage(FORM_STATE_KEY)
alert('데이터를 불러오는데 에러가 발생했습니다.')
return
}
서버에서 가져온 데이터들을 스토리지에 저장된 데이터와 비교할 수 있도록 동일한 포맷으로 맞춥니다.
const selectedMemo = orderSheetPayload.deliveryAddress.deliveryMemos.find((memo) => memo.reuseMemo) ?? null
const initialUiStateFromServer: UiStateFromServer = {
useVirtualPhoneNumber: false,
selectedMemo,
reuseMemo: !!selectedMemo,
useAllCoupon: true,
}
깊은 비교인 isEqual을 통해 스토리지에 저장된 이전 데이터와 서버로부터 받아온 데이터를 비교합니다. 만약 사용자가 원복을 원하면 데이터들을 원복합니다. 이후 스토리지 값은 초기화됩니다.
if (
!isEqual(storageData, initialUiStateFromServer) &&
window.confirm('이전에 입력한 내용이 있습니다. 이어서 작성하시겠습니까?')
) {
dispatch(restoreDeliveryAddressState(storageData))
dispatch(restoreUseAllCouponState(storageData))
}
removeStateFromSessionStorage(FORM_STATE_KEY)