Files
shoptime/com.twin.app.shoptime/src/hooks/useTermsStateMachine.js
2025-06-22 22:19:57 +09:00

95 lines
3.0 KiB
JavaScript

import { useState, useCallback } from "react";
const useTermsStateMachine = (initialState) => {
const [isTransitioning, setIsTransitioning] = useState(false);
const [state, setState] = useState({
termsChecked: false,
privacyChecked: false,
optionalChecked: false,
selectAllChecked: false,
error: null, // 1. 에러 상태 추가
...initialState,
});
const updateStateAsync = useCallback(
async (updates) => {
if (isTransitioning) {
const err = new Error("State transition already in progress.");
if (process.env.NODE_ENV === "development") {
console.warn("[useTermsStateMachine] Rejected:", err.message);
}
// 2. 에러 상태를 설정하고 throw
setState((s) => ({ ...s, error: err }));
throw err;
}
setIsTransitioning(true);
// 3. 이전 에러 상태 초기화
setState((s) => ({ ...s, error: null }));
try {
const newState = await new Promise((resolve) => {
setState((currentState) => {
const nextState = { ...currentState, ...updates };
const {
termsChecked: currentTerms,
privacyChecked: currentPrivacy,
optionalChecked: currentOptional,
} = currentState;
const termsChecked =
"termsChecked" in updates
? updates.termsChecked
: currentTerms;
const privacyChecked =
"privacyChecked" in updates
? updates.privacyChecked
: currentPrivacy;
const optionalChecked =
"optionalChecked" in updates
? updates.optionalChecked
: currentOptional;
if (
"termsChecked" in updates ||
"privacyChecked" in updates ||
"optionalChecked" in updates
) {
nextState.selectAllChecked =
termsChecked && privacyChecked && optionalChecked;
} else if ("selectAllChecked" in updates) {
nextState.termsChecked = updates.selectAllChecked;
nextState.privacyChecked = updates.selectAllChecked;
nextState.optionalChecked = updates.selectAllChecked;
}
if (process.env.NODE_ENV === "development") {
console.log(
"[useTermsStateMachine] State transition:",
currentState,
"->",
nextState
);
}
resolve(nextState);
return nextState;
});
});
setIsTransitioning(false);
return newState;
} catch (error) {
setIsTransitioning(false);
console.error("[useTermsStateMachine] State update failed:", error);
// 4. 에러 상태를 설정하고 다시 throw
setState((s) => ({ ...s, error }));
throw error;
}
},
[isTransitioning]
);
return { state, updateStateAsync };
};
export default useTermsStateMachine;