#javascript #reactjs #material-ui
Вопрос:
Я использую пользовательский интерфейс Material для создания нового пользователя..некоммерческая организация необязательна. Но у меня возникла проблема с проверкой формы, а затем выходом из проверки, чтобы я мог отправлять данные пользователей в axios по запросу. любая помощь будет признательна.
Я не уверен, как реорганизовать этот код, чтобы позволить мне это сделать. Я попробовал пользовательский хук и создал новый файл, но я просто запутался.
const useStyles = makeStyles((theme) => ({
root: {
'amp; .MuiTextField-root': {
margin: theme.spacing(1),
width: 288,
borderRadius: 8,
},
},
button: {
width: 288,
borderRadius: 8,
},
}));
// eslint-disable-next-line react/prop-types
export default function CreateAccountMuiForm() {
const classes = useStyles();
const [emailError, setEmailError] = useState('');
const [passwordError, setPasswordError] = useState('');
// const [nonProfitError, setNonProfitError] = useState('');
const [showPassword, setShowPassword] = useState(false);
const handleClickShowPassword = () => setShowPassword(!showPassword);
const handleMouseDownPassword = () => setShowPassword(!showPassword);
const [values, setValues] = useState({
email: '',
password: '',
nonProfit: '',
});
const handleChange = (e) => {
const { name, value } = e.target;
setValues({
...values,
[name]: value,
});
};
const handleSubmit = async (e) => {
e.preventDefault();
// sets intial state to false
setEmailError(false);
setPasswordError(false);
// // form validation happens here after submited
// // this checks to make sure a valid email is input
if (values.email === '') {
setEmailError(true);
} else if (!/S @S .S /.test(values.email)) {
setEmailError(true);
}
// this checks to make sure password is greater than 5
if (values.password === '') {
setPasswordError(true);
} else if (values.password.length < 5) {
setPasswordError(true);
}
// this checks to make sure both validations are true
if (values.email amp;amp; values.password) {
// eslint-disable-next-line no-console
console.log(values);
}
return
};
return (
<FormControl>
<form className={classes.root} noValidate autoComplete="off" onSubmit={handleSubmit}>
<div>
<TextField
name="email"
id="outlined-password-input"
placeholder="Email"
type="email"
autoComplete="current-email"
variant="outlined"
required
error={emailError}
value={values.email}
onChange={handleChange}
// onChange={(e) => setEmail(e.target.value)}
/>
<TextField
name="password"
id="password"
placeholder="password"
type={showPassword ? 'text' : 'password'}
autoComplete="current-password"
variant="outlined"
required
error={passwordError}
value={values.password}
onChange={handleChange}
// onChange={(e) => setPassword(e.target.value)}
InputProps={{ // <-- This is where the toggle button is added.
endAdornment: (
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
>
{showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
),
}}
/>
<TextField
name="nonProfit"
id="nonProfit"
placeholder="Select you nonprofit (optional)"
type="text"
autoComplete="none"
variant="outlined"
// onChange={(e) => setNonProfit(e.target.value)}
value={values.nonProfit}
onChange={handleChange}
// error={nonProfitError}
/>
<Button
variant="contained"
type="submit"
className={classes.button}
>
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>
);
}
Ответ №1:
TL; DR: Следуйте принципам низкой связи и высокой когезии: разделите значения состояний и сопоставьте их с состояниями ошибок, чтобы вы могли проверить их с помощью крючков.
NL; PR: Отличный вопрос, это часто упускается из виду в учебных пособиях. В этом прошлом вы можете увидеть способ сделать это. Это соответствующие фрагменты:
Не
- Высокая связь: ненужная зависимость между значениями состояния:
const [values, setValues] = useState({
email: '',
password: '',
nonProfit: '',
});
- Низкая когезия: состояние ошибки выводится из другого значения:
const [emailError, setEmailError] = useState('');
Делать
- Низкая связь: отдельная обработка состояния для каждого значения, высокая согласованность: значение электронной почты и ошибка обрабатываются в одном месте (крючок).
const useEmailValidator = () => {
const [value, setValue] = useState("");
const [emailError, setEmailError] = useState(false);
const handleAndValidateEmail = useCallback((value) => {
setEmailError(!(value amp;amp; /S @S .S /.test(value)));
setValue(value);
}, []);
return [value, handleAndValidateEmail, emailError];
};
Попробуйте провести рефакторинг других значений состояния и ошибок с помощью крючков валидатора.
Наконец, если вы чувствуете себя предприимчивым, рассмотрите принцип DRY и попробуйте библиотеки управления формами.
Комментарии:
1. Не могли бы вы создать отдельную функцию для запроса POST, а затем указать ее в возврате? Или выйти из этой функции, а затем создать совершенно другую функцию отправки для отправки запроса на публикацию?
2. Я обновил пример =), поскольку для отправки требуется проверка нескольких значений состояния (их нельзя разделить), я изменил вашу функцию handleSubmit, чтобы проверить наличие ошибок перед выполнением выборки Axios.