編輯:對于訪問此問題的任何人 - 閱讀 onRequest 和 onCall 函式之間的區別。了解如何在客戶端代碼中呼叫它們。它應該有助于理解這里的問題。
我正在構建一個個人專案,后端使用 firebase,前端使用 React。我正在嘗試從云函式中正確回傳錯誤。客戶端顯示的錯誤不是從服務器發送的。我將在下面演示這個問題。
我希望客戶端顯示“電子郵件地址已被另一個帳戶使用”的錯誤。正如您從下面的螢屏截圖中看到的那樣,這就是作為回應物件發送的內容。但是,每當我在客戶端執行 console.log(err.message) 時,它都會顯示“invalid-argument”。(請參閱下面螢屏截圖中的控制臺日志)。
索取資料
這是代碼。
云函式 - index.ts
export const registerUser = https.onRequest((req, resp) => {
cors(req, resp, async () => {
const data = req.body.data;
const userData: IUserData = {
firstName: data.firstName,
lastName: data.lastName,
statusId: 1,
customerId: ''
}
try {
// Create auth user in firebase
const newAuthUser = await admin.auth().createUser({
email: data.email,
emailVerified: false,
password: data.password,
displayName: data.firstName ' ' data.lastName,
disabled: false
})
// Create a stripe customer
const uid = newAuthUser.uid;
const stripeCustomer = await createStripeCustomer(data, uid);
userData.customerId = stripeCustomer.id;
// Create user doc in firestore
const storeUserRef = app.firestore().doc('/users/' uid);
const storeUser = await storeUserRef.set(userData);
resp.status(200).json({
user: storeUser,
message: "User successfully registered"
}).send();
return;
} catch (err: any) {
console.log(err);
resp.status(400).send(err);
return;
}
})
})
反應 - SignupPage.tsx
function SignUpPage() {
const firebaseAuth = getAuth(FIREBASE_APP);
const functions = getFunctions(FIREBASE_APP);
const [auth, loading] = useAuthState(firebaseAuth);
const [regError, setRegError] = useState("")
const nav = useNavigate();
const { register, handleSubmit, formState: { errors }, } = useForm();
const [registering, setRegistering] = useState(false);
const registerUser = httpsCallable(functions, 'registerUser');
connectFunctionsEmulator(functions, "localhost", 5001);
// Check if a user login exists
useEffect(() => {
// If the auth has finished loading and the user exists, redirect to the
// user account page
if (auth && !loading) { nav('/account') }
}, [auth, loading, nav])
/**
* Form on submit
* @param data
*/
const onSubmit = (data: any) => {
setRegistering(true);
setRegError("");
const userData: IRegisterPayload = {
firstName: data.firstName,
lastName: data.lastName,
email: data.email,
password: data.password
}
registerUser(userData).then(async(res) => {
// return await signInWithEmailAndPassword(
// firebaseAuth, userData.email, userData.password
// );
console.log('REGISTER USER SUCCESS: ', res)
})
.then(res => {
console.log(res);
nav("/account");
})
.catch((err) => {
console.log('Console log err.message:', err.message);
setRegError(err.message);
}).finally(() => {
setRegistering(false);
})
};
return(
<SiteLayout>
<div className="px-3 py-5 mx-auto signup-wrapper w-100 container d-flex flex-column flex-grow-1">
<div className="row">
<div className="col-12 col-lg-6 col-xl-5 pe-lg-5">
<h2 className="h2 mb-4 text-center">Sign up</h2>
<p className="text-center">Already a member? <NavLink to={`/login`}>Login</NavLink></p>
<form onSubmit={handleSubmit(onSubmit)}
className="mb-2"
>
<div className="mb-3">
<label>First Name</label>
<input type={`text`}
className={`form-control${errors.firstName ? ' is-invalid': ''}`}
placeholder="Enter your first name"
disabled={registering}
{...register('firstName', { required: true})}
/>
{errors.firstName && <small className="text-danger d-block mt-1">First Name is required</small>}
</div>
<div className="mb-3">
<label>Last Name</label>
<input type={`text`}
className={`form-control${errors.lastName ? ' is-invalid': ''}`}
placeholder="Enter your last name"
disabled={registering}
{...register('lastName', { required: true})}
/>
{errors.lastName && <small className="text-danger d-block mt-1">Last Name is required</small>}
</div>
<div className="mb-3">
<label>Email</label>
<input type={`email`}
className={`form-control${errors.email ? ' is-invalid': ''}`}
placeholder="Enter your email address"
disabled={registering}
{...register('email', { required: true})}
/>
{errors.email && <small className="text-danger d-block mt-1">Email is required</small>}
</div>
<div className="mb-4">
<label>Password</label>
<input type={`password`}
className={`form-control${errors.password ? ' is-invalid': ''}`}
placeholder="Enter your password"
disabled={registering}
{...register('password',{
required: "You must specify a password",
validate: (val: string) => {
// Check the entered value meets the regex requirement
const isStrong = PASSWORD_REGEX.test(val);
return (val && isStrong) || "Password does not meet criteria";
}
})}
/>
{errors.password && <p className="small text-danger d-block my-1">{errors.password.message}</p>}
<small className="text-muted">Passwords must be a minimum of 8 characters and include:</small>
<ul className="small text-muted">
<li>At least 1 uppercase letter</li>
<li>At least 1 lowercase letter</li>
<li>At least 1 special character</li>
<li>At least 1 number</li>
</ul>
</div>
<Button isLoading={registering}
isSubmit={true}
loadingLabel="Registering..."
className="w-100"
>
Sign up
</Button>
{regError &&
<Message severity="error" text={regError} className="my-3 w-100" />
}
</form>
<p className="small text-muted">
By signing up, you confirm that you accept the Terms of Service and Privacy Policy. This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.
</p>
</div>
</div>
</div>
</SiteLayout>
);
}
export default SignUpPage;
有人可以告訴我如何顯示我想要的錯誤訊息嗎?
uj5u.com熱心網友回復:
在您的客戶端應用程式中,您說 regusterUser 是一個“可呼叫”型別的函式,但它并沒有以這種方式部署在您的后端。
// here you are saying that the backend is a "callable" type function
const registerUser = httpsCallable(functions, 'registerUser');
但是,您的后端使用的是普通的 HTTP onRequest型別函式。
// here are you deploying a normal HTTP function (not "callable")
export const registerUser = https.onRequest((req, resp) => {
這是行不通的——你不能將 HTTP 型別的函式呼叫為可呼叫物件。
如果您想在后端使用可呼叫型別函式,請按照檔案中的說明使用onCall型別函式。從該鏈接檔案中,請注意:
請務必記住,HTTPS 可呼叫函式與 HTTP 函式相似但不完全相同。要使用 HTTPS 可呼叫函式,您必須使用適用于您平臺的客戶端 SDK 以及 functions.https 后端 API(或實作協議)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/496530.html
標籤:javascript 反应 火力基地 firebase 身份验证 谷歌云功能
