问题
I'm trying to implement a form using react-hook-form. I'm not able to actually connect the data and event working correctly. As the docs state, I'm using the handleSubmit
function from the react-hook-form library, with my custom Axios post as the onSubmit
parameter: onSubmit={handleSubmit(onSubmit)
According to my Vscode, the data and event are not registering correctly const onSubmit = (data, e) => {}
.
When the form is submitted, the web console logs an empty form:
{email: "", password: ""}
What am I doing wrong with my code? Note for sake of brevity, I removed the password textfield below.
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>
How can I link up everything correctly and get my input data and event to communicate with the onSubmit={handleSubmit(onSubmit)
inside my form?
Thank you for the help!
EDIT:
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});
}
}
/>
回答1:
Why not use the data
parameter on the onSubmit
function?
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,
}))
})
};
Using this Controller
component inside the 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>}
回答2:
onSubmit
only has one argument in its callback function & its the event
.. Where you can get the data using event.target
array or event.target.elements."fieldname"
(fieldname is the name
of the input field) or event.target.fieldname.value
....
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,
}))
})
};
Well, just remove the data
parameter...
回答3:
Looking at
const handleChange = (e) => {
updateFormData({
...formData,
});
};
and
<TextField
...
onChange={handleChange}
...
/>
It seems like the onChange simply isn't changing the state. You're probably going to want to do something like this:
onChange={
(evt) => {
let key = evt.currentTarget.name;
let value = evt.currentTarget.value;
handleChange({[key]: value});
}
}
and then
const handleChange = (e) => {
updateFormData({
...formData,
...e
});
};
This should work for the password field if the "name" attribute is "password".
来源:https://stackoverflow.com/questions/66003394/react-my-form-is-submitting-empty-data-because-e-and-data-are-declared-but