React登录请求返回数据后页面被覆盖无数据的问题求助
React登录请求后页面被覆盖问题解决
问题描述
我正在学习React,遇到了一个异常问题:
- 当发送无数据的API请求(故意未预先处理异常)时,响应能正常返回并显示预期异常;
- 但发送带邮箱、密码的登录请求时,API返回数据后页面会立刻被覆盖,无法理解为何会触发新请求。
代码片段
sendLogin函数
async function sendLogin(userLoginModel: LoginModelView) { let data = userLoginModel; await fetch(i.login.url, { method: i.login.methodType, body: JSON.stringify(data), headers: { "Content-Type": "application/json", }, }) .then((response) => { var prom; if (response.ok) { prom = response.json() as Promise<ResultModel<UserModel>>; prom.then((result) => { setUser(result.data); handOverAlert( new AlertModel({ message: result.message, isSuccess: result.isSuccess, }) ); }); } else { prom = response.json() as Promise<ResultModel<boolean>>; prom.then((result) => { setUser(new UserModel()); handOverAlert( new AlertModel({ message: result.message, isSuccess: result.isSuccess, }) ); }); } }) .catch((error) => console.log(error)); }
Login组件
export default function Login() { const [login, setLogin] = useState<LoginModelView>({email:"", password:""}); const { sendLogin } = useAuth() function handelChange(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) { const {name, value} = e.target; setLogin(prevlogin => ({ ...prevlogin, [name]:value })) } function send() { sendLogin(login) // 调用API的函数 } return ( <Container component="main" maxWidth="xs"> <CssBaseline /> <Paper sx={{ marginTop: "3%", display: 'flex', flexDirection: 'column', alignItems: 'center', }} > <Avatar sx={{ margin: "1%", backgroundColor: "red", }}> <LockIcon /> </Avatar> <Typography component="h1" variant="h5"> Přihlášení </Typography> <form> <FormControl sx={{ width:"100%", marginTop: "1%" }}> <TextField variant="outlined" margin="normal" required fullWidth id="email" label="Email" autoComplete="email" autoFocus name="email" value={login.email} onChange={e => handelChange(e)} /> <TextField variant="outlined" margin="normal" required fullWidth name="password" label="Heslo" type="password" id="password" autoComplete="current-password" value={login.password} onChange={e => handelChange(e)} /> <Button sx={{ margin: "1%" }} type="submit" fullWidth variant="contained" color="primary" onClick={send} > Přihlásit </Button> <Grid container> <Grid item xs> <Link href="/ForgotPassword" variant="body2"> Zapomenuté heslo? </Link> </Grid> <Grid item xs> <Link href="/Register" variant="body2"> {"Nejste registrováni? Registrujte se"} </Link> </Grid> </Grid> </FormControl> </form> </Paper> </Container> ); }
问题原因及解决方法
核心原因
页面被覆盖是因为表单的默认提交行为:你的按钮type="submit",点击后会触发<form>标签的默认提交动作,导致浏览器刷新页面,覆盖之前的API响应状态。
解决方法(任选其一)
方法1:阻止表单默认提交行为
修改send函数,接收事件参数并调用preventDefault():
function send(e: React.FormEvent) { e.preventDefault(); // 阻止表单默认提交 sendLogin(login); }
方法2:修改按钮类型为button
将按钮的type从submit改为button,避免触发表单提交:
<Button sx={{ margin: "1%" }} type="button" // 改为button类型 fullWidth variant="contained" color="primary" onClick={send} > Přihlásit </Button>
方法3:绑定表单的onSubmit事件
在<form>标签上绑定onSubmit事件,处理提交逻辑并阻止默认行为:
<form onSubmit={(e) => { e.preventDefault(); sendLogin(login); }}>
额外优化:统一async/await风格
你的sendLogin函数混用了async/await和.then(),建议统一使用async/await让代码更简洁易读:
async function sendLogin(userLoginModel: LoginModelView) { try { const response = await fetch(i.login.url, { method: i.login.methodType, body: JSON.stringify(userLoginModel), headers: { "Content-Type": "application/json", }, }); if (response.ok) { const result = await response.json() as ResultModel<UserModel>; setUser(result.data); handOverAlert(new AlertModel({ message: result.message, isSuccess: result.isSuccess, })); } else { const result = await response.json() as ResultModel<boolean>; setUser(new UserModel()); handOverAlert(new AlertModel({ message: result.message, isSuccess: result.isSuccess, })); } } catch (error) { console.log(error); } }
内容的提问来源于stack exchange,提问作者Radim Cieslar
相关产品推荐
相关产品推荐

