Since I'm learning how to build React forms with hooks, I went through the 3 quicks posts that culminate with this one . Everything is going well until I get to the last step when you create your custom hook with:
function useFormInput(initialValue) {
const [value, setValue] = useState(initialValue);
function handleChange(e) {
setValue(e.target.value);
}
return {
value,
onChange: handleChange
};
}
The Input is:
const Input = ({ type, name, onChange, value, ...rest }) => (
<input
name={name}
type={type}
value={value}
onChange={event => {
event.preventDefault();
onChange(name, event.target.value);
}}
{...rest}
/>
);
And the Form is:
const Form = () => {
const email = useFormInput("");
const password = useFormInput("");
return (
<form
onSubmit={e =>
e.preventDefault() || alert(email.value) || alert(password.value)
}
>
<Input
name="email"
placeholder="e-mail"
type="email"
{...email}
/>
<Input
name="password"
placeholder="password"
type="password"
{...password}
/>
<input type="submit" />
</form>
);
};
So in useFormInput()
Chrome complains about
TypeError: Cannot read property 'value' of undefined at handleChange
which I'm pretty sure is pointing me to
function handleChange(e) {
setValue(e.target.value);
}
If I console.log(e) I get 'email', as expected (I think?), but if I try console.log(e.target) I get undefined. So obviously e.target.value doesn't exist. I can get it working by just using
setValue(document.getElementsByName(e)[0].value);
but I don't know what kind of issues this might have. Is this a good idea? Are there drawbacks to getting it to work this way?
Thanks
The issue comes from the onChange
prop in the Input
component
onChange={event => {
event.preventDefault();
onChange(name, event.target.value);
}}
you're calling onChange
like this onChange(name, event.target.value);
(two arguments, the first one is a string), while in your custom hook you define the callback like this
function handleChange(e) {
setValue(e.target.value);
}
it's expecting one argument, an event.
So either call onChange
with one argument (the event) :
onChange={event => {
event.preventDefault();
onChange(event);
}}
or change the implementation of the callback.
Try this out:
const handleChange = e => {
const { inputValue } = e.target;
const newValue = +inputValue;
setValue(newLimit);
};
Had this issue with a calendar picker library react-date-picker using Register API . Looking at the documentation found out that there's another way of handling components that don't return the original event object on the onChange function using the Controller API .
More details on Controller API Docs
Example:
/*
* React Function Component Example
* This works with either useForm & useFormContext hooks.
*/
import { FC } from 'react'
import { Controller, useFormContext } from 'react-hook-form'
import DatePicker,{ DatePickerProps } from 'react-date-picker/dist/entry.nostyle'
const FormDateInput: FC<Omit<DatePickerProps, 'onChange'>> = ({
name,
...props
}) => {
const formMethods = useFormContext()
const { control } = formMethods ?? {}
return (
<Controller
render={({ field }) => <DatePicker {...props} {...field} />}
name={name ?? 'date'}
control={control}
/>
)
}
export default FormDateInput
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.