Hello, I am attempting to utilize the Formik Field component along with a custom, internally developed TextInput component. Unfortunately, it appears that even after I wire-up the form.handleChange event, the field is not showing as touched when typing into it. Here's my component code:
import React, { Component } from 'react';
import { TextInput } from '@cjones/forms';
import { Field } from 'formik';
import PropTypes from 'prop-types';
class TextInputWrappedInternal extends Component {
static propTypes = {
field: PropTypes.shape().isRequired,
form: PropTypes.shape().isRequired,
label: PropTypes.string.isRequired
};
constructor(props) {
super(props);
this.touched = false;
}
handleChange = event => {
const {
field: { name },
form: { handleChange, setFieldTouched }
} = this.props;
if (!this.touched) {
this.touched = true;
setFieldTouched(name, true);
}
handleChange(event);
};
render() {
const { field, label } = this.props;
return (
<TextInput onChange={this.handleChange} value={field.value} name={field.name} label={label} {...this.props} />
);
}
}
export default props => <Field component={TextInputWrappedInternal} {...props} />;
As you can see, I need to manually call the form.setFieldTouched function as without it, the field is not showing as touched after being touched. Unfortunately, I also need to check whether this has already been done as I see severe performance degradation when calling setFieldTouched on each keystroke -- not to mention it's unnecessary.
Any thoughts? Thanks!
Have you tried using props.form.touched[name] to check for this information?
@Saifadin -- yes, unfortunately the information only shows up within that object _after_ I manually call setFieldTouched.
For instance, if I have:
<TextInputWrapped name="testText" label="Test Text"/>
My props.form.touched is empty until setFieldTouch is called. It doesn't even show as testText: false, surprisingly enough.
Can you provide the place, where you call that Component from? Basically the <Formik> container
Sure, take a look below--the onSubmit properly displays my TextInput value as well:
import React from 'react';
import { Formik, Form, Field } from 'formik';
import TextInputWrapped from 'shared/components/forms/TextInputWrapped';
const initialModel = {
textInputTest: ''
};
export default () => (
<div>
<h1>Dashboard</h1>
<Formik
initialValues={initialModel}
onSubmit={(values, actions) => {
console.log('values: ', values);
console.log('actions: ', actions);
}}
render={() => (
// values, errors, touched, handleBlur, handleChange, isSubmitting
<Form>
<TextInputWrapped name="textInputTest" label="Text Input" />
<Button type="submit" kind="primary">
Submit
</Button>
</Form>
)}
/>
</div>
);
It seems to work for me 馃槄, can you recreate it in codesandbox and provide a url.
@Saifadin -- it works fine with the setFieldTouched code, but without it, as shown in the CodeSandbox below, you can see what I'm talking about:
https://codesandbox.io/s/7mmmk82q9q
I feel like handleChange should cover setting the field to touched (without a manual call to setFieldTouched), unless I'm missing something..?
You need to pass handleBlur or call setFieldTouched after blur on the input.
Most helpful comment
You need to pass handleBlur or call setFieldTouched after blur on the input.