React - Моя форма отправляет пустые данные, потому что 'e' и 'data' объявлены, но никогда не используются?

Я пытаюсь реализовать форму с помощью response-hook-form. Я не могу правильно подключить данные и событие. Как указано в документации, я использую функцию handleSubmit из библиотеки response-hook-form с моим настраиваемым сообщением Axios в качестве параметра onSubmit: onSubmit={handleSubmit(onSubmit)

Согласно моему Vscode, данные и событие регистрируются неправильно const onSubmit = (data, e) => {}.

При отправке формы веб-консоль регистрирует пустую форму: {email: "", password: ""}

Что я делаю не так со своим кодом? Обратите внимание, что для краткости я удалил текстовое поле пароля ниже.

export default function SignIn()
{
    const { register, control, errors: fieldsErrors, handleSubmit } = useForm()
    const history = useHistory();
    const initialFormData = Object.freeze({
        email: '',
        password: '',
    });

    const [formData, updateFormData] = useState(initialFormData);

    const handleChange = (e) => {
        updateFormData({
            ...formData,
        });
    };

    const dispatch = useDispatch();
    
    const onSubmit = (data, e) => {
            console.log(formData);
        
            axiosInstance
                .post(`auth/token/`, {
                    grant_type: 'password',
                    username: formData.email,
                    password: formData.password,
                })
                .then((res) => {
                    console.log(res);
                    localStorage.setItem('access_token', res.data.access_token);
                    localStorage.setItem('refresh_token', res.data.refresh_token);
                    history.push('/');
                    window.location.reload();
                    dispatch(login({
                        name: formData.email,
                        password: formData.password,
                        loggedIn: true,
                    }))
                })
        
        };

    const classes = useStyles();

    return (
        <Container component="main" maxWidth="xs">
            <CssBaseline />
            <div className={classes.paper}>
                <Typography component="h1" variant="h5">
                    Sign in
                </Typography>
                <form className={classes.form} noValidate onSubmit={handleSubmit(onSubmit)}>
                    <FormControl fullWidth variant="outlined">
                        <Controller
                            name="email"
                            as={
                                <TextField
                                    variant="outlined"
                                    margin="normal"
                                    inputRef={register}
                                    required
                                    fullWidth
                                    id="email"
                                    label="Email Address"
                                    name="email"
                                    autoComplete="email"
                                    autoFocus
                                    onChange={handleChange}
                                    helperText={fieldsErrors.email ? fieldsErrors.email.message : null}
                                    error={fieldsErrors.email}
                                />
                            }
                            control={control}
                            defaultValue=""
                            rules={{
                                required: 'Required',
                                pattern: {
                                value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i,
                                message: 'invalid email address'
                                }
                            }}
                        />  
                    </FormControl>

Как я могу правильно связать все и получить мои входные данные и событие для связи с onSubmit={handleSubmit(onSubmit) внутри моей формы?

Спасибо вам за помощь!

РЕДАКТИРОВАТЬ:

export default function SignIn()
{
    const { register, control, errors: fieldsErrors, handleSubmit } = useForm()
    const history = useHistory();
    const initialFormData = Object.freeze({
        email: '',
        password: '',
    });

    const [formData, updateFormData] = useState(initialFormData);

    const handleChange = (e) => {
        updateFormData({
          ...formData,
          ...e
        });
      };

    const dispatch = useDispatch();
    
    const onSubmit = (data, e) => {
            console.log(formData);
        
            axiosInstance
                .post(`auth/token/`, {
                    grant_type: 'password',
                    username: formData.email,
                    password: formData.password,
                })
                .then((res) => {
                    console.log(res);
                    localStorage.setItem('access_token', res.data.access_token);
                    localStorage.setItem('refresh_token', res.data.refresh_token);
                    history.push('/');
                    window.location.reload();
                    dispatch(login({
                        name: formData.email,
                        password: formData.password,
                        loggedIn: true,
                    }))
                })
        
        };


    return (
        <Container component="main" maxWidth="xs">
            <CssBaseline />
            <div className={classes.paper}>
                <Typography component="h1" variant="h5">
                    Sign in
                </Typography>
                <form className={classes.form} noValidate onSubmit={handleSubmit(onSubmit)}>
                    <FormControl fullWidth variant="outlined">
                        <Controller
                            name="email"
                            as={
                                <TextField
                                    variant="outlined"
                                    margin="normal"
                                    inputRef={register}
                                    required
                                    fullWidth
                                    id="email"
                                    label="Email Address"
                                    name="email"
                                    autoComplete="email"
                                    autoFocus
                                    onChange={
                                        (evt) => {
                                          let key = evt.currentTarget.name;
                                          let value = evt.currentTarget.value;
                                          handleChange({[key]: value});
                                        }
                                      }
                                    helperText={fieldsErrors.email ? fieldsErrors.email.message : null}
                                    error={fieldsErrors.email}
                                />
                            }
                            control={control}
                            defaultValue=""
                            rules={{
                                required: 'Required',
                                pattern: {
                                value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i,
                                message: 'invalid email address'
                                }
                            }}
                        />  
                    </FormControl>
                    <TextField
                        variant="outlined"
                        margin="normal"
                        inputRef={register}
                        required
                        fullWidth
                        name="password"
                        label="Password"
                        type="password"
                        id="password"
                        autoComplete="current-password"
                        onChange={
                            (evt) => {
                              let key = evt.currentTarget.name;
                              let value = evt.currentTarget.value;
                              handleChange({[key]: value});
                            }
                          }
                    />

person woof    schedule 02.02.2021    source источник


Ответы (3)


Почему бы не использовать параметр data в функции onSubmit?

const onSubmit = (data, e) => {
        console.log(data);
    
        axiosInstance
            .post(`auth/token/`, {
                grant_type: 'password',
                username: data.email,
                password: data.password,
            })
            .then((res) => {
                console.log(res);
                localStorage.setItem('access_token', res.data.access_token);
                localStorage.setItem('refresh_token', res.data.refresh_token);
                history.push('/');
                window.location.reload();
                dispatch(login({
                    name: data.email,
                    password: data.password,
                    loggedIn: true,
                }))
            })
    
    };

Использование этого Controller компонента внутри form

  <Controller
    as={
      <TextField
        variant="outlined"
        margin="normal"
        fullWidth
        label="Email Address"
        autoComplete="email"
        autoFocus
        error={Boolean(fieldsErrors.email)}
      />
    }
    name="email"
    control={control}
    rules={{
      required: 'Required',
      pattern: {
      value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i,
      message: 'invalid email address'
      }
    }}
    defaultValue=""
  />
  {fieldsErrors.email?.type && <p>{fieldsErrors.email?.message}</p>}
person mj.    schedule 02.02.2021

onSubmit имеет только один аргумент в своей функции обратного вызова и event .. Где вы можете получить данные, используя массив event.target или event.target.elements."fieldname" (имя поля - это name поля ввода) или _6 _....

onSubmit:

const onSubmit = (e) => {
            console.log(formData);
        
            axiosInstance
                .post(`auth/token/`, {
                    grant_type: 'password',
                    username: formData.target.email.value,
                    password: formData.target.password.value,
                })
                .then((res) => {
                    console.log(res);
                    localStorage.setItem('access_token', res.data.access_token);
                    localStorage.setItem('refresh_token', res.data.refresh_token);
                    history.push('/');
                    window.location.reload();
                    dispatch(login({
                        name: formData.email,
                        password: formData.password,
                        loggedIn: true,
                    }))
                })
        
        };

Ну просто убери параметр data ...

person KR Tirtho    schedule 02.02.2021
comment
Привет, спасибо за комментарий. См. Следующие документы: react-hook-form.com/api#handleSubmit The onSubmit требует двух параметров data и e. Я пробовал иметь только e, но у меня все еще возникает та же проблема, о которой говорилось в моем сообщении. - person woof; 02.02.2021

Смотря на

const handleChange = (e) => {
    updateFormData({
        ...formData,
    });
};

а также

<TextField
...
onChange={handleChange}
...
/>

Похоже, что onChange просто не меняет состояние. Вероятно, вы захотите сделать что-то вроде этого:

onChange={
  (evt) => {
    let key = evt.currentTarget.name;
    let value = evt.currentTarget.value;
    handleChange({[key]: value});
  }
}

а потом

const handleChange = (e) => {
  updateFormData({
    ...formData,
    ...e
  });
};

Это должно работать для поля пароля, если атрибут имени - пароль.

person Michael Hoobler    schedule 02.02.2021
comment
Пожалуйста, ознакомьтесь с моими изменениями в исходном сообщении. Я реализовал ваш пример, но все еще не могу заставить код работать. Я не получаю {email: "", password: "", undefined: "password"} в ответ, а сейчас создается неопределенное поле? Можете ли вы подтвердить, правильно ли я реализовал ваш метод? - person woof; 02.02.2021
comment
@Dre Вы хотите изменить let key = evt.currentTarget.password на let key = evt.currentTarget.name в атрибуте onChange. Та же ошибка в поле ввода электронной почты. :) - person Michael Hoobler; 02.02.2021
comment
Спасибо, что указали на это :). Мне удалось получить правильный ответ для поля моего пароля в консоли, но поле моего адреса электронной почты все еще пусто? Даже несмотря на то, что я перешел на упомянутые вами исправления? Айв снова отредактировал свой исходный пост, чтобы показать внесенные им изменения. - person woof; 02.02.2021
comment
@Dre Хм ... ошибок тоже нет? Если нет, не могли бы вы попробовать заменить let key = evt.currentTarget.name в электронном письме onChange на let key = 'email' и посмотреть, заставит ли это работать? - person Michael Hoobler; 02.02.2021
comment
Никаких ошибок, также ваша рекомендация, к сожалению, не сработала. Я думаю, проблема в том, как я обрабатываю ошибки? Поле пароля не имеет проверки или сообщения / правил об ошибке, поле сравниваемого адреса электронной почты. Тем не менее, поле пароля в ответе работает нормально. - person woof; 02.02.2021
comment
@Dre Похоже, что это так. К сожалению, я не слишком хорошо знаком с правилами проверки. Я также видел в react-hook-form документах, что as скоро устареет и что render - это новая вещь, которая его заменит. Может, стоит попробовать? Надеюсь, ты найдешь решение. - person Michael Hoobler; 02.02.2021
comment
Тем не менее, спасибо, что помогли мне приблизиться к решению этой проблемы! - person woof; 02.02.2021