I've got a React Native application (0.57.0), using Formik (1.5.7). I've got a component that is a screen (a top-level react-navigation route). The form submit button appears in the header, via the component's static navigationOptions. So I'm using withFormik to make the form's values and touched objects available to the header. The form field values are updating as expected, but the touched object is not updating. (Note: My form component is also wrapped by react-redux connect.)
I've had to create a wrapper around the Formik handleChange method to get them to update properly:
handleChange = field => (value) => {
const { setTouched, handleChange, touched } = this.props;
setTouched({
...touched,
[field]: true,
});
handleChange(field)(value);
}
This seems like a total hack, though it does appear to be working. I'd like to know if anyone knows why this might be happening. If I don't monkey patch handleChange the touched object remains empty when I inspect this.props from anywhere in the component.
Here are some examples of my field components. They are just Picker and TextField components from React Native wrapped in styled-components.
<ProvincePicker
value={values.province}
placeholder={account.residence}
onChange={handleChange('province')}
provinces={this.props.provinces}
required
inline
style={styles.provincePickerStyle}
/>
and
<PhoneInput
onChangeText={handleChange('phone')}
value={values.phone}
placeholder={phonePlaceholder}
required={! this.isPhoneOptional()}
style={styles.phoneInputStyle}
/>
I'm grabbing handleChange and values from this.props, and using withFormik to instantiate the component's form data:
const FormikAccount = withFormik({
mapPropsToValues: props => pickAccountFields(props.authUser),
})(Account);
export default connect(mapStateToProps, mapDispatchToProps)(FormikAccount);
pickAccountFields just returns an object:
const pickAccountFields = (authUser) => {
const {
name, phone, email, province, phone_type: phoneType, patient,
} = authUser;
const birthdayAt = new Date(patient.data.birthday_at.date);
const { gender } = patient.data;
const [firstName, lastName] = name.split(' ');
return {
firstName,
lastName,
phone,
email,
province,
phoneType: phoneType || 'mobile',
birthdayAt,
gender,
};
};
That this.props.touched will automatically update when handleChange is called.
| Software | Version(s) |
| ---------------- | ---------- |
| Formik | 1.5.7
| React | 16.5.0
| React-Native | 0.57.0
| npm/Yarn | 1.15.2
| Operating System | MacOS Mojave 10.14.5
Any word on this?
I came across this because I was having a similar issue with the field name not showing up in the touched object even though I had touched it. Not the exact scenario for you but maybe something helpful in it...
I was using the <Field render={({ field }) => (<CustomInput {...field} />)} /> method, to render a custom input field, and pass the formik field props (onChange, onBlur, name and value) from to the input element rendered in my <CustomInput /> via the { ...field} spread (as documented here).
Digging into the source I found that its the onBlur that ultimately sets the touched status via the executeBlur method here, and in my code I wasn't passing the event object through to on my <CustomInput /> components onBlur handler, (I was just calling onBlur, e.g. onBlur={() => { props.onBlur(); ) which resulted in no event object and therefore no field to use for Formik to know which property was touched. Updating my onBlur prop to `onBlur={(e) => { props.onBlur(e); ) resolved the issue for me.
I don't know much about the ReactNative environment, but maybe the Picker or TextField are not triggering the onBlur (handleBlur/executeBlur in Formik code) 馃 or maybe if they are they're not passing the right event data?
same issue but in react js
In React Native, handleBlur needs to be called like this in order for touched to be updated. Docs are here: https://jaredpalmer.com/formik/docs/guides/react-native
<TextField
onChangeText={handleChange('email')}
onBlur={handleBlur('email')}
value={values.email}
/>
@denofprojects I imagine you're having the same problem, but in web. Maybe a third party input? If an event is not being passed back from your component's onBlur, then you'll also need to handleBlur(fieldName).
The same issue, but in reactJs.
Most helpful comment
I came across this because I was having a similar issue with the field name not showing up in the
touchedobject even though I had touched it. Not the exact scenario for you but maybe something helpful in it...I was using the
<Field render={({ field }) => (<CustomInput {...field} />)} />method, to render a custom input field, and pass the formik field props (onChange,onBlur,nameandvalue) from to the input element rendered in my<CustomInput />via the{ ...field}spread (as documented here).Digging into the source I found that its the
onBlurthat ultimately sets the touched status via theexecuteBlurmethod here, and in my code I wasn't passing the event object through to on my<CustomInput />components onBlur handler, (I was just callingonBlur, e.g.onBlur={() => { props.onBlur(); )which resulted in no event object and therefore nofieldto use for Formik to know which property was touched. Updating my onBlur prop to `onBlur={(e) => { props.onBlur(e); )resolved the issue for me.I don't know much about the ReactNative environment, but maybe the
PickerorTextFieldare not triggering theonBlur(handleBlur/executeBlur in Formik code) 馃 or maybe if they are they're not passing the right event data?