I'm using Formik for validation in a React app.
Validation is working correctly, but my onChange handler does not fire:
<Field
type="text"
name="name"
placeholder="First Name"
component={Input}
onChange={() => console.log("gfdg")}
/>
Link to Sandbox
Why is this?
Inside Input, the way you have ordered the props passed to your input element means your onChange is being overwritten by Formik's onChange. When you create a Field with a custom component (i.e. Input in your case), Formik passes its FieldProps to the component. FieldProps contains a property field that contains various handlers including onChange.
In your Input component you do this (I've removed the irrelevant props):
<input
onChange={onChange}
{...field}
/>
See how your own onChange will just get replaced by Formik's onChange() inside field? To make it clearer ...field is basically causing this to happen:
<input
onChange={onChange}
onChange={field.onChange}
// Other props inside "field".
/>
If you were to reorder those the console message will now appear:
<input
{...field}
onChange={onChange}
/>
However now your input won't work now because you do need to call Formik's onChange to let Formik now when your input changes. If you want both a custom onChange event and for your input to work properly you can do it like this:
import React from "react";
import { color, scale } from "./variables";
const Input = React.forwardRef(
({ onChange, onKeyPress, placeholder, type, label, field, form }, ref) => (
<div style={{ display: "flex", flexDirection: "column" }}>
{label && (
<label style={{ fontWeight: 700, marginBottom: `${scale.s2}rem` }}>
{label}
</label>
)}
<input
{...field}
ref={ref}
style={{
borderRadius: `${scale.s1}rem`,
border: `1px solid ${color.lightGrey}`,
padding: `${scale.s3}rem`,
marginBottom: `${scale.s3}rem`
}}
onChange={changeEvent => {
form.setFieldValue(field.name, changeEvent.target.value);
onChange(changeEvent.target.value);
}}
onKeyPress={onKeyPress}
placeholder={placeholder ? placeholder : "Type something..."}
type={type ? type : "text"}
/>
</div>
)
);
export default Input;
See it here in action.
Although overall I'm not really sure what you're trying to do. Your form is working fine, you probably don't need a custom onChange but maybe you have some specific use case.
Let me first make it clear this answer is just for help purpose and I do know that this question has been accepted but I do have some modification for above answer with my version if the above solution doesn't work for anyone
Here onChangeText will return the value of the quantity field
<Formik
initialValues={{ product_id: '', quantity: '', amount: '' }}
onSubmit={(values, actions) => {
this.submitLogin(values);
}}
//some other elements ....
<Field placeholder='No. of Quantity' name='quantity' component={CustomInputComponent}
onChangeText={value => {
console.warn(value); // will get value of quantity
}}
/>
/>
Outside of your class you can define your component
const CustomInputComponent = ({
onChangeText,
field, // { name, value, onChange, onBlur }
form: { touched, errors, isValid, handleBlur, handleChange, values, setFieldValue }, // also values, setXXXX, handleXXXX, dirty, isValid, status, etc.
...props
}) => {
return (
<Input {...field} {...props} onBlur={handleBlur(field.name)}
onChangeText={value => {
setFieldValue(field.name, value);
onChangeText(value); // calling custom onChangeText
}}
/>
)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With