React-Appwrite登录表单报错:loginForm.current.email/undefined问题排查
解决React+Appwrite登录表单的"loginForm.current.email is undefined"错误
问题根源
你的登录表单中,email和password输入框没有设置name属性,导致通过form ref访问loginForm.current.email和loginForm.current.password时找不到对应元素,触发undefined错误。DOM表单元素的属性访问是基于name或id标识的,必须显式声明才能通过form实例直接获取。
修复步骤
1. 给输入框添加name属性
修改StudentLogin组件里的表单输入部分,给邮箱和密码输入框加上对应name:
<form ref={loginForm} onSubmit={handleSubmit}> <div> <label>Username</label> {/* 添加name="email" */} <input type="email" name="email" className="text-input" required /> </div> <div> <label>Password</label> {/* 添加name="password" */} <input type="password" name="password" className="text-input" required /> </div> {/* 其他代码不变 */} </form>
2. 修复路由跳转的依赖问题
原代码中useEffect的依赖数组为空,不会监听user状态变化,导致用户登录后无法自动跳转。需要把user和navigate加入依赖:
useEffect(() => { if (user) { navigate("/protect"); } }, [user, navigate]); // 添加依赖
3. 完善AuthContext的登录状态校验(可选但必要)
当前AuthContext没有在组件挂载时检查用户登录状态,刷新页面后用户状态会丢失。修改AuthProvider的useEffect,添加登录状态校验:
useEffect(() => { const checkAuthStatus = async () => { try { const currentUser = await account.get(); setUser(currentUser); } catch (error) { // 用户未登录,忽略错误 console.log("User not logged in"); } finally { setLoading(false); } }; checkAuthStatus(); }, []);
完整修复后的代码片段
StudentLogin组件
import React, { useEffect, useRef } from "react"; import { Link, useNavigate } from "react-router-dom"; import { useAuth } from "../../utils/AuthContext"; import "./loginPages.css"; const StudentLogin = () => { const navigate = useNavigate(); const { user, loginUser } = useAuth(); const loginForm = useRef(null); useEffect(() => { if (user) { navigate("/protect"); } }, [user, navigate]); const handleSubmit = (e) => { e.preventDefault(); const email = loginForm.current.email.value; const password = loginForm.current.password.value; const userInfo = { email, password }; loginUser(userInfo); }; return ( <div className="login container"> <div className="wrapper"> <div className="login-container"> <div className="login-wrapper"> <h2 className="login-header"> <Link to="/protect">Login</Link> </h2> <form ref={loginForm} onSubmit={handleSubmit}> <div> <label>Username</label> <input type="email" name="email" className="text-input" required /> </div> <div> <label>Password</label> <input type="password" name="password" className="text-input" required /> </div> <div className="checkbox"> <label htmlFor="remember-me"> <input type="checkbox" id="remember-me" /> Remember me </label> </div> <input type="submit" value="Login" className="login-btn btn" /> </form> <div className="or"> <hr className="bar" /> <span>OR</span> <hr className="bar" /> </div> <Link to="/prtportal" className="other-btn"> Login as Parent </Link> </div> <footer className="login-footer"> <p>Copyright © 2023 Azure. All rights reserved.</p> <div> <Link className="login-footer-link" to="/"> Terms of Use </Link>{" "} |{" "} <Link className="login-footer-link" to="/"> Privacy Policy </Link> </div> </footer> </div> </div> </div> ); }; export default StudentLogin;
AuthContext组件
import { useContext, useState, useEffect, createContext } from "react"; import { account } from "../appwriteConfig"; const AuthContext = createContext(); export const AuthProvider = ({ children }) => { const [loading, setLoading] = useState(true); const [user, setUser] = useState(null); useEffect(() => { const checkAuthStatus = async () => { try { const currentUser = await account.get(); setUser(currentUser); } catch (error) { console.log("User not authenticated"); } finally { setLoading(false); } }; checkAuthStatus(); }, []); const loginUser = async (userInfo) => { setLoading(true); try { await account.createEmailSession(userInfo.email, userInfo.password); const accountDetails = await account.get(); setUser(accountDetails); } catch (error) { console.error(error); } finally { setLoading(false); } }; const logoutUser = async () => { try { await account.deleteSession("current"); setUser(null); } catch (error) { console.error(error); } }; const checkUserStatus = async () => { try { const currentUser = await account.get(); setUser(currentUser); return currentUser; } catch (error) { setUser(null); return null; } }; const contextData = { user, loginUser, logoutUser, checkUserStatus, }; return ( <AuthContext.Provider value={contextData}> {loading ? <p>loading...</p> : children} </AuthContext.Provider> ); }; export const useAuth = () => { return useContext(AuthContext); }; export default AuthContext;
内容的提问来源于stack exchange,提问作者Jean Mako
相关产品推荐
相关产品推荐

