반응형
게시글 제목을 어떻게 써야할지도 모르겠는데 어떻게든 내가 삽질하다가 구현 완료된거를 공유하고 싶었다
우선 내가 원했던 플로우는
로그인 화면 -> 회원가입 이동 -> 즉시 약관동의 바텀시트 띄움
1. 약관 필수 동의 모두 체크 -> 완료 -> 회원가입 진행
2. 필수 동의 미체크 -> 완료 -> 필수 체크 안내 알림 모달 띄움 -> 확인
-> 다시 1번 진행 or 뒤로가기 백핸들러 실행 -> 바텀시트 닫히고 로그인 화면 이동
3. 필수 동의 미체크로 백드랍 터치 시 바텀시트 닫히지 않게 방어
4. 아무것도 동작하지 않고 백핸들러 작동하면 바텀시트 닫히고 로그인 화면 이동
그런데 문제 상황은
로그인 화면 -> 회원가입 이동 -> 즉시 약관동의 바텀시트 띄움
1. 약관 필수 동의 모두 체크 -> 완료 -> 회원가입 진행
2. 필수 동의 미체크 -> 완료 -> 필수 체크 안내 알림 모달 띄움 -> 확인
-> 다시 1번 진행 or ** 뒤로가기 백핸들러 작동 안함 **
3. 필수 동의 미체크로 백드랍 터치 시 바텀시트 닫히지 않게 방어
4. 아무것도 동작하지 않고 백핸들러 작동하면 바텀시트 닫히고 로그인 화면 이동
2번에서 필수 체크 안내 모달이 뜬 후에는 백핸들러 버튼을 아무리 눌러도 아무런 반응이 없다는 것이었다.
일단 해결법부터 설명하자면
//import문 생략
import { magicModal } from "react-native-magic-modal";
export default function SignUpScreen() {
const router = useRouter();
const agreeToTermsRef = useRef<AgreeToTermsRef>(null);
const isAgreedRef = useRef(false);
const methods = useForm<Signup>({
resolver: zodResolver(signupSchema),
mode: "onChange",
defaultValues: {
step: "stepOne",
loginId: "",
email: "",
emailConfirm: "",
password: "",
passwordConfirm: "",
nickname: "",
},
});
const { watch } = methods;
const step = watch("step");
const showTermsBottomSheet = () => {
openBottomSheet(
{
title: "약관 동의",
content: () => <AgreeToTermsAndConditionsModal ref={agreeToTermsRef} />,
buttons: [
{
text: "완료",
onPress: () => {
const isValid = agreeToTermsRef.current?.validate();
if (!isValid) {
openModal({
title: "필수 항목 동의가 필요해요",
content: "모든 필수 약관 항목을 확인 후 동의해주세요",
buttons: [
{
text: "확인",
secondary: true,
onPress: () => {
magicModal.hideAll();
showTermsBottomSheet();
},
},
],
});
return false;
}
isAgreedRef.current = true;
},
},
],
},
true,
{
onBackButtonPress: () => {
if (!isAgreedRef.current) {
openModal({
title: "약관 동의가 필요해요",
content: "회원가입을 위해서는 필수 약관에 동의해야 합니다.\n정말 나가시겠어요?",
buttons: [
{
text: "나가기",
secondary: true,
onPress: () => {
magicModal.hideAll();
router.back();
},
},
{ text: "취소" },
],
});
return true;
}
return false;
},
onBackdropPress: () => {
if (!isAgreedRef.current) return true;
return false;
},
},
);
};
useEffect(() => {
showTermsBottomSheet();
return () => {
magicModal.hideAll();
};
}, []);
return (
<View className="flex-1">
<FormProvider {...methods}>
{step === "stepOne" && <SignupForm />}
{step === "stepTwo" && <NicknameForm />}
{step === "stepThree" && <CompleteForm />}
</FormProvider>
</View>
);
}
약관 동의 체크를 하지 않고 바텀시트의 완료 버튼을 누르면 알림 모달이 뜨고, 다시 확인 버튼을 누른 후 백핸들러를 동작시킬 때
회원가입 진행하지 않고 나가는지 알림 모달을 다시 띄우는 방법이다.
분기처리 내용을 다시 자세히 보면
const showTermsBottomSheet = () => {
openBottomSheet(
{
title: "약관 동의",
content: () => <AgreeToTermsAndConditionsModal ref={agreeToTermsRef} />,
buttons: [
{
text: "완료",
onPress: () => {
const isValid = agreeToTermsRef.current?.validate();
if (!isValid) {
openModal({
title: "필수 항목 동의가 필요해요",
content: "모든 필수 약관 항목을 확인 후 동의해주세요",
buttons: [
{
text: "확인",
secondary: true,
onPress: () => {
// 현재 떠 있는 모든 모달과 바텀시트를 전부 닫음
magicModal.hideAll();
// 약관 바텀시트만 다시 즉시 띄움
showTermsBottomSheet();
},
},
],
});
// 바텀 시트를 닫지 말라는 신호
return false;
}
isAgreedRef.current = true;
},
},
],
},
// 기본 닫힘(backdrop, back button) 허용
true,
{
onBackButtonPress: () => {
if (!isAgreedRef.current) {
openModal({
title: "약관 동의가 필요해요",
content: "회원가입을 위해서는 필수 약관에 동의해야 합니다.\n정말 나가시겠어요?",
buttons: [
{
text: "나가기",
secondary: true,
onPress: () => {
// 모든 모달 닫고
magicModal.hideAll();
// 이전 화면 이동
router.back();
},
},
{ text: "취소" },
],
});
// 백버튼으로 바텀시트 닫는 걸 막음
return true;
}
// 약관 동의 완료 상태면 바텀시트 닫아도 됨
return false;
},
onBackdropPress: () => {
// 동의 안 했으면 닫힘 차단
if (!isAgreedRef.current) return true;
// 동의 했으면 닫힘 허용
return false;
},
},
);
};
좀 복잡해서 나도 아직 헷갈리긴 한데 계속 해보면서 이해하면 될 것 같다 !
반응형
'React Native' 카테고리의 다른 글
| react native 다양한 애니메이션 효과 사이트 (0) | 2025.12.29 |
|---|---|
| react native 키패드 있을 때 버튼 함수 바로 실행하는 방법 (0) | 2025.12.23 |
| react native 컴포넌트 높이 구하기 (0) | 2025.12.22 |
| eas build는 됐는데 eas submit이 안될 때 (0) | 2025.12.18 |
| expo eas update 안되는 문제 해결 / call to function expoUpdates.checkForUpdateAsync has bee rejected. caused by failed to check for update (0) | 2025.12.18 |