Material UI表单校验后调用axios POST提交数据问题求助
解决方案
核心问题说明
当前代码在校验通过后仅打印了表单数据日志,没有编写axios请求逻辑,也没有对校验结果做拦截判断,所以无法提交数据。
直接修改现有代码的方案
第一步:安装依赖并新增状态
首先安装axios(已安装可跳过)
npm install axios
在组件头部引入axios,同时新增提交loading、提交结果提示状态,避免重复提交:
import axios from 'axios' // 其余原有import保持不变 export default function CreateAccountMuiForm() { const classes = useStyles(); // 原有状态保留,新增以下状态 const [loading, setLoading] = useState(false) const [submitMsg, setSubmitMsg] = useState('') // ...其余原有状态
第二步:修改handleSubmit提交逻辑
替换原有handleSubmit逻辑,校验通过后触发axios POST请求:
const handleSubmit = async (e) => { e.preventDefault(); setEmailError(false); setPasswordError(false); setSubmitMsg(''); let isValid = true; if (!values.email || !/\S+@\S+\.\S+/.test(values.email)) { setEmailError(true); isValid = false; } if (!values.password || values.password.length < 5) { setPasswordError(true); isValid = false; } // 校验不通过直接终止流程 if (!isValid) return; try { setLoading(true) // 替换为实际后端注册接口地址 const res = await axios.post('/api/user/register', { email: values.email, password: values.password, // 非盈利组织字段仅传非空值,也可直接传空字符串,可根据后端要求调整 ...(values.nonProfit.trim() && {nonProfit: values.nonProfit}) }) // 提交成功后可自定义后续逻辑,比如跳转到登录页、清空表单 setSubmitMsg('注册成功') setValues({email: '', password: '', nonProfit: ''}) } catch (err) { // 可根据后端返回的错误格式调整提示内容 setSubmitMsg(err.response?.data?.message || '注册失败,请稍后重试') } finally { setLoading(false) } };
第三步:页面新增提示和按钮loading状态
修改按钮组件并添加提交结果提示:
{/* 提交结果提示 */} {submitMsg && <p style={{color: submitMsg.includes('成功') ? 'green' : 'red', marginLeft: '8px'}}>{submitMsg}</p>} <Button variant="contained" type="submit" className={classes.button} disabled={loading} > {loading ? '提交中...' : 'Create an account'} </Button>
抽离自定义Hook方案
可把表单状态、校验、提交逻辑抽为单独文件useRegisterForm.js,实现逻辑复用,简化组件代码:
自定义Hook代码(useRegisterForm.js)
import { useState } from 'react' import axios from 'axios' export default function useRegisterForm() { const [values, setValues] = useState({ email: '', password: '', nonProfit: '', }) const [errors, setErrors] = useState({ email: false, password: false }) const [loading, setLoading] = useState(false) const [submitMsg, setSubmitMsg] = useState('') const handleChange = (e) => { const { name, value } = e.target setValues(prev => ({...prev, [name]: value})) // 输入时清除对应字段的错误提示 if (errors[name]) setErrors(prev => ({...prev, [name]: false})) } const handleSubmit = async (e, successCallback) => { e.preventDefault() setErrors({email: false, password: false}) setSubmitMsg('') let isValid = true if (!values.email || !/\S+@\S+\.\S+/.test(values.email)) { setErrors(prev => ({...prev, email: true})) isValid = false } if (!values.password || values.password.length < 5) { setErrors(prev => ({...prev, password: true})) isValid = false } if (!isValid) return try { setLoading(true) const res = await axios.post('/api/user/register', { email: values.email, password: values.password, ...(values.nonProfit.trim() && {nonProfit: values.nonProfit}) }) setSubmitMsg('注册成功') setValues({email: '', password: '', nonProfit: ''}) // 支持传入成功回调,比如跳转登录页 successCallback?.() return res.data } catch (err) { setSubmitMsg(err.response?.data?.message || '注册失败,请稍后重试') return Promise.reject(err) } finally { setLoading(false) } } return { values, errors, loading, submitMsg, handleChange, handleSubmit } }
组件中使用自定义Hook
原组件可简化为:
// 其余原有import保持不变,移除原有表单状态、校验、提交逻辑 import useRegisterForm from './useRegisterForm' export default function CreateAccountMuiForm() { const classes = useStyles(); const [showPassword, setShowPassword] = useState(false); const handleClickShowPassword = () => setShowPassword(!showPassword); const handleMouseDownPassword = () => setShowPassword(!showPassword); // 引入自定义Hook const {values, errors, loading, submitMsg, handleChange, handleSubmit} = useRegisterForm() return ( <FormControl> <form className={classes.root} noValidate autoComplete="off" onSubmit={(e) => handleSubmit(e, () => console.log('提交成功后自定义逻辑'))}> <div> <TextField name="email" placeholder="Email" type="email" autoComplete="current-email" variant="outlined" required error={errors.email} value={values.email} onChange={handleChange} /> <TextField name="password" placeholder="password" type={showPassword ? 'text' : 'password'} autoComplete="current-password" variant="outlined" required error={errors.password} value={values.password} onChange={handleChange} InputProps={{ endAdornment: ( <InputAdornment position="end"> <IconButton aria-label="toggle password visibility" onClick={handleClickShowPassword} onMouseDown={handleMouseDownPassword} > {showPassword ? <Visibility /> : <VisibilityOff />} </IconButton> </InputAdornment> ), }} /> <TextField name="nonProfit" placeholder="Select you nonprofit (optional)" type="text" autoComplete="none" variant="outlined" value={values.nonProfit} onChange={handleChange} /> {submitMsg && <p style={{color: submitMsg.includes('成功') ? 'green' : 'red', margin: '8px'}}>{submitMsg}</p>} <Button variant="contained" type="submit" className={classes.button} disabled={loading} > {loading ? '提交中...' : 'Create an account'} </Button> <p className="terms-of-use"> By creating an account you agree to our <Link to="/termsofuse" style={{ textDecoration: 'none', color: '#909090' }}> <strong> Terms of use</strong> </Link> </p> </div> </form> </FormControl> ); }
内容的提问来源于stack exchange,提问作者andy86
相关产品推荐
相关产品推荐

