React中users数组在handleSignUpSubmit函数外为空的问题求助
问题原因及解决方案
核心问题分析
- 组件渲染重置数组:
users数组定义在组件函数顶层,React每次渲染组件时都会重新创建这个空数组。哪怕你在注册时往数组里push了数据,组件重新渲染后数组会被重置为空,所以在handleSignUpSubmit外访问时,它始终是空的。 - 对象引用导致匹配失效:用
users.includes(loginUserDetails)永远返回false,因为includes比较的是对象引用——你创建的loginUserDetails是新对象,和users里的对象引用不同,哪怕内容完全一致也匹配不上。 - 未从localStorage读取数据:登录逻辑里没有从localStorage取出已存储的用户列表,而是直接用组件里的空数组,自然无法匹配到注册过的用户。
修复后的完整代码
import { useRef, useState } from "react"; import styles from "../../styles/Login/Login.module.css"; interface User { username: string; password: string; } const Login = (): JSX.Element => { const signUpRef = useRef<HTMLInputElement>(null); const signUpPasswordRef = useRef<HTMLInputElement>(null); const loginRef = useRef<HTMLInputElement>(null); const loginPasswordRef = useRef<HTMLInputElement>(null); // 用state存储用户列表,初始化时从localStorage读取已有数据 const [users, setUsers] = useState<User[]>(() => { const storedUsers = localStorage.getItem("user"); return storedUsers ? JSON.parse(storedUsers) : []; }); const handleSignUpSubmit = (e: React.FormEvent) => { e.preventDefault(); const userDetails: User = { username: signUpRef.current!.value, password: signUpPasswordRef.current!.value, }; // 创建新数组更新state,同步到localStorage const updatedUsers = [...users, userDetails]; setUsers(updatedUsers); localStorage.setItem("user", JSON.stringify(updatedUsers)); signUpPasswordRef.current!.value = ""; signUpRef.current!.value = ""; }; const handleLoginSubmit = (e: React.FormEvent) => { e.preventDefault(); const loginUserDetails: User = { username: loginRef.current!.value, password: loginPasswordRef.current!.value, }; // 比较对象属性而非引用,判断用户是否存在 const isUserExist = users.some(user => user.username === loginUserDetails.username && user.password === loginUserDetails.password ); isUserExist ? console.log("Welcome Back!") : console.log("Check your username or password again"); loginRef.current!.value = ""; loginPasswordRef.current!.value = ""; }; return ( <> <form onSubmit={handleSignUpSubmit}> <h1>Sign Up</h1> <div> <label htmlFor="signup-username">Username</label> <input type="text" name="signup-username" className={styles.username} ref={signUpRef} id="signup-username" autoComplete="username" /> </div> <div> <label htmlFor="signup-password">Password</label> <input type="password" name="signup-password" className={styles.password} ref={signUpPasswordRef} id="signup-password" autoComplete="new-password" /> </div> <button type="submit">Sign Up</button> </form> <form onSubmit={handleLoginSubmit}> <h1>Login</h1> <div> <label htmlFor="login-username">Username</label> <input type="text" name="login-username" className={styles.username} id="login-username" ref={loginRef} autoComplete="username" /> </div> <div> <label htmlFor="login-password">Password</label> <input type="password" name="login-password" className={styles.password} id="login-password" ref={loginPasswordRef} autoComplete="current-password" /> </div> <button type="submit">Log In</button> </form> </> ); }; export default Login;
关键修复点说明
- 用useState持久化用户数据:state会在组件渲染时保留数据,不会被重置,初始化时从localStorage读取已有用户,保证页面刷新后数据不丢失。
- 更新数组时同步到localStorage:通过扩展运算符创建新数组,避免直接修改原state,同时把新数组存入localStorage。
- 改用some方法匹配用户:直接比较
username和password属性,替代依赖对象引用的includes方法。 - 修正autoComplete属性:使用标准属性值,提升表单的自动填充体验。
内容的提问来源于stack exchange,提问作者Neelam
相关产品推荐
相关产品推荐

