Проблемы с проверкой формы пользовательского интерфейса материала

#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.