[Firebase] Firebase App named '[DEFAULT]' already exists with different options or config (app/duplicate-app).
- 파이어베이스 설정을 하고 작업을 진행하려 하니 오류가 나왔다.
찾아보니 앱을 중복해서 초기화하는 문제가 발생할 수 있다고 한다.
파이어베이스 앱이 있는지 확인하고 없을 때 새로 초기화 하는 방식으로 해야한다고 해서 수정을 했다.
파이어베이스 중복 오류
src > firebase > firebase.ts
import { getApp, getApps, initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_API_KEY,
authDomain: process.env.NEXT_PUBLIC_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_MESSAGING_ID,
appId: process.env.NEXT_PUBLIC_APP_ID,
};
// Initialize Firebase
// const app = initializeApp(firebaseConfig); //기존 코드
const app = !getApps().length ? initializeApp(firebaseConfig) : getApp();
export const auth = getAuth(app);
회원가입
components > login > formJoin.tsx
const onSubmit = async (e: React.ChangeEvent<HTMLFormElement>) => {
e.preventDefault();
if (!emailRegex.test(email)) {
setError("이메일 형식이 올바르지 않습니다.");
setFormError(true);
} else if (password?.length < 8) {
setError("비밀번호는 8자리 이상으로 입력해주세요.");
setFormError(true);
} else if (password.length > 0 && password !== passwordConfirm) {
setError("비밀번호와 비밀번호 확인 값이 다릅니다.");
setFormError(true);
} else {
setError("");
setFormError(false);
await register(email, password);
openModal("completed");
}
};
- 이메일 정규식은 블로그를 참고해서 썼다.
- /^ : 시작
- $/ : 끝
- [A-Za-z0-9] : 영문 대소문자 혹은 숫자로 시작
- ([-_.][A-Za-z0-9]) : 두 번째 글자부터는 영문 대소문자 혹은 숫자이며 - _ .이 들어갈 수 있음
- * : 문자 또는 숫자가 0개 이상 나타남
- @가 중간에 반드시 들어가야 함
- 도메인 부분도 마찬가지로 영문 대소문자 혹은 숫자로 시작하며 그 다음부터-_.이 들어갈 수 있음
- . 이 최소한 하나는 반드시 들어가야 함
- .뒤에 com과 같은 최상위 도메인이 들어갈 자리 2-3자리 지정
- + 참고) i : 전체에 대해서 대소문자를 구분하지 않음
- 이메일, 비밀번호가 맞지 않으면 오류메세지를 출력해야하기 때문에 setError에 메세지를 적어주고
- setFormError는 에러 상태를 부모 컴포넌트에 전달해서 css로 스타일을 주고 싶어서 추가하였다.
- 조건이 다 맞으면 등록이 되고 모달창을 띄운다.
// 모달 닫고 새로고침
const closeModal = () => {
router.back();
setTimeout(() => {
router.reload();
}, 300);
};
- 모달 커스텀훅의 기존 closeModal을 사용하지 않고 새로고침을 추가하기 위해 새로 작성하였다.
** 수정 **
회원가입을 하고 로그인창으로 이동시키려 했지만
파이어베이스는 회원가입을 하면 자동으로 로그인이 된다...
상황에 맞게 코드를 바꿨다.
const getUserId = () => ({
email: emailInput.current?.value ?? "",
password: pwdInput.current?.value ?? "",
passwordConfirm: pwdConfirmInput.current?.value ?? "",
});
const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const { email, password, passwordConfirm } = getUserId();
if (!emailRegex.test(email)) {
setError("이메일 형식이 올바르지 않습니다.");
setFormError(true);
} else if (password?.length < 8) {
setError("비밀번호는 8자리 이상으로 입력해주세요.");
setFormError(true);
} else if (password.length > 0 && password !== passwordConfirm) {
setError("비밀번호와 비밀번호 확인 값이 다릅니다.");
setFormError(true);
} else {
setError("");
setFormError(false);
openModal("completed");
}
};
const closeModal = async () => {
const { email, password } = getUserId();
try {
await register(email, password);
} catch (error) {
console.log(error);
setError("회원가입 중 문제가 발생했습니다.");
}
};
- ref로 input의 값을 가져온다.
- onSubmit 이벤트에서 register를 하지 않고 모달 모달 띄우기까지만 한 뒤
closeModal 이벤트에서 register()를 해주었다.
링크 이동 이벤트가 없는 것은 login 화면에서 로그인이 된 상태에서 /login으로 접근하면 /홈화면으로 이동하게 했기 때문,,
전체코드
더보기
export default function FormJoin({
setFormError,
}: {
setFormError: (value: boolean) => void;
}) {
const emailInput = useRef<HTMLInputElement>(null);
const pwdInput = useRef<HTMLInputElement>(null);
const pwdConfirmInput = useRef<HTMLInputElement>(null);
const [error, setError] = useState<string>("");
const { currentModal, openModal } = useModal();
const emailRegex =
/^[A-Za-z0-9]([-_.]?[A-Za-z0-9])*@[A-Za-z0-9]([-_.]?[A-Za-z0-9])*\.[A-Za-z]{2,3}$/i;
async function register(email: string, password: string) {
try {
return await createUserWithEmailAndPassword(auth, email, password);
} catch (error) {
console.log(error);
}
}
const getUserId = () => ({
email: emailInput.current?.value ?? "",
password: pwdInput.current?.value ?? "",
passwordConfirm: pwdConfirmInput.current?.value ?? "",
});
const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const { email, password, passwordConfirm } = getUserId();
if (!emailRegex.test(email)) {
setError("이메일 형식이 올바르지 않습니다.");
setFormError(true);
} else if (password?.length < 8) {
setError("비밀번호는 8자리 이상으로 입력해주세요.");
setFormError(true);
} else if (password.length > 0 && password !== passwordConfirm) {
setError("비밀번호와 비밀번호 확인 값이 다릅니다.");
setFormError(true);
} else {
setError("");
setFormError(false);
openModal("completed");
}
};
const closeModal = async () => {
const { email, password } = getUserId();
try {
await register(email, password);
} catch (error) {
console.log(error);
setError("회원가입 중 문제가 발생했습니다.");
}
};
return (
<Form onSubmit={onSubmit}>
<p>Email</p>
<input
name="email"
type="email"
placeholder="이메일을 입력해주세요."
required
ref={emailInput}
/>
<p className="pwd">Password</p>
<input
name="password"
type="password"
placeholder="비밀번호를 입력해주세요."
required
ref={pwdInput}
/>
<input
name="passwordConfirm"
type="password"
placeholder="비밀번호를 다시 입력해주세요."
required
ref={pwdConfirmInput}
/>
{error && <p className="error">{error}</p>}
<input className="btn" type="submit" value="Sign Up" />
{currentModal === "completed" && (
<Modal
currentModal={currentModal}
hide={closeModal}
message="회원가입이 완료되었습니다."
subMessage="자동으로 로그인이 됩니다."
type="info"
/>
)}
</Form>
);
}
'언어 > Next.js' 카테고리의 다른 글
[Next 고캠핑] 로컬 데이터 파이어베이스로 변경하기 (0) | 2024.08.21 |
---|---|
[Next 고캠핑] 로그인 상태관리, 로그아웃 (2) | 2024.08.14 |
[Next 고캠핑] 뒤로가기 클릭시 모달창 닫기 (0) | 2024.08.12 |
[Next 고캠핑] 모달 만들기 (1) | 2024.07.31 |
[Next 고캠핑] 커스텀훅으로 alert창 만들기 (0) | 2024.07.27 |