表单提交时useEffect首次未触发问题排查与修复求助
问题:useEffect首次提交校验失败,二次点击才生效
代码实现
const Login=(props)=> { const [password,setPassword]=useState(null); const [readytosubmit,setReadytosubmit]=useState(false) const nameRef=useRef("dim"); var name=nameRef.current.value; const passwordRef=useRef(""); console.log(name) useEffect(()=>{ const getArticles = async () => { const res = await Axios.get("http://localhost:8080/api/password/"+name); setPassword(res.data); console.log(password); }; getArticles()},[readytosubmit]) function handlesubmit(e){ //must need e.preventDefault(); setReadytosubmit(true); console.log(nameRef.current.value) console.log(password) console.log(passwordRef.current.value) if(passwordRef.current.value.toString()===password.toString()){ console.log("Ture Password") props.login();}else{ console.log("false password") } } return ( <> <div className='Registerform'> <h3>Login Form</h3><br></br> <Form onSubmit={handlesubmit} > <Form.Group className="mb-3" controlId="formBasicName"> <Form.Label>Username</Form.Label> <Form.Control ref={nameRef} type="username" placeholder="Enter your username" /> </Form.Group><br></br> <Form.Group className="mb-3" controlId="formBasicPassword"> <Form.Label>Password</Form.Label> <Form.Control ref={passwordRef} type="password" placeholder="Password" /> </Form.Group><br></br> <Button variant="primary" type="submit"> Submit </Button> </Form> </div> <Button onClick={props.login} variant="primary">Primary</Button> </> ) } export default Login ;
控制台日志
login.jsx:41 alex <-- i click the submitform login.jsx:42 <--empty result which is expected the password get from the database login.jsx:43 123456 login.jsx:47 false password login.jsx:22 alex login.jsx:22 alex login.jsx:30 login.jsx:22 alex login.jsx:22 alex login.jsx:41 alex login.jsx:42 123456 login.jsx:43 123456 <----have the resubmit after double click login.jsx:45 Ture Password index.js:32 loginstatusfalse index.js:33 login layout.jsx:28 layout: true layout.jsx:28 layout: true login.jsx:22 alex login.jsx:22 alex
问题原因
- 用户名未实时获取:
var name=nameRef.current.value定义在组件顶层,仅在组件初始化或重新渲染时执行。用户输入用户名后,组件不会因ref变化触发更新,导致第一次提交时useEffect使用的是初始旧值,请求结果不符合预期。 - 异步状态更新时机错误:第一次点击submit时,
setReadytosubmit(true)触发组件重渲染,但handlesubmit会立刻校验password——此时useEffect的异步请求尚未完成,password仍是初始的null,因此校验失败。 - 依赖项设计冗余:依赖
readytosubmit触发请求的逻辑不合理,第一次点击后该状态变为true,后续点击不会再触发状态变更,自然不会触发useEffect。第二次校验成功只是因为第一次useEffect已完成请求并更新了password,并非第二次触发了useEffect。
修复方案
方案一:直接在提交时发起请求(推荐,逻辑更简洁)
去掉readytosubmit状态和useEffect,直接在handlesubmit中完成请求、校验和登录流程:
const Login=(props)=> { const nameRef=useRef("dim"); const passwordRef=useRef(""); async function handlesubmit(e){ e.preventDefault(); const username = nameRef.current.value; const inputPassword = passwordRef.current.value; try { const res = await Axios.get(`http://localhost:8080/api/password/${username}`); const dbPassword = res.data; if(inputPassword.toString() === dbPassword.toString()){ console.log("True Password"); props.login(); }else{ console.log("false password"); } } catch (error) { console.error("获取密码失败:", error); } } return ( <> <div className='Registerform'> <h3>Login Form</h3><br></br> <Form onSubmit={handlesubmit} > <Form.Group className="mb-3" controlId="formBasicName"> <Form.Label>Username</Form.Label> <Form.Control ref={nameRef} type="username" placeholder="Enter your username" /> </Form.Group><br></br> <Form.Group className="mb-3" controlId="formBasicPassword"> <Form.Label>Password</Form.Label> <Form.Control ref={passwordRef} type="password" placeholder="Password" /> </Form.Group><br></br> <Button variant="primary" type="submit"> Submit </Button> </Form> </div> <Button onClick={props.login} variant="primary">Primary</Button> </> ) } export default Login ;
方案二:调整useEffect依赖与状态逻辑(保留原模式优化)
用state跟踪用户名变化,确保useEffect能实时获取最新输入,并在password更新后再执行校验:
const Login=(props)=> { const [password,setPassword]=useState(null); const [username, setUsername] = useState(""); const passwordRef=useRef(""); const handleNameChange = (e) => { setUsername(e.target.value); }; useEffect(()=>{ if(!username) return; const getArticles = async () => { const res = await Axios.get(`http://localhost:8080/api/password/${username}`); setPassword(res.data); }; getArticles(); },[username]) function handlesubmit(e){ e.preventDefault(); const inputPassword = passwordRef.current.value; if(password && inputPassword.toString() === password.toString()){ console.log("True Password"); props.login(); }else{ console.log("false password"); } } return ( <> <div className='Registerform'> <h3>Login Form</h3><br></br> <Form onSubmit={handlesubmit} > <Form.Group className="mb-3" controlId="formBasicName"> <Form.Label>Username</Form.Label> <Form.Control value={username} onChange={handleNameChange} type="username" placeholder="Enter your username" /> </Form.Group><br></br> <Form.Group className="mb-3" controlId="formBasicPassword"> <Form.Label>Password</Form.Label> <Form.Control ref={passwordRef} type="password" placeholder="Password" /> </Form.Group><br></br> <Button variant="primary" type="submit"> Submit </Button> </Form> </div> <Button onClick={props.login} variant="primary">Primary</Button> </> ) } export default Login ;
内容的提问来源于stack exchange,提问作者user20112858
相关产品推荐
相关产品推荐

