Formik: Why do I need to manually call setFieldTouched?

Created on 3 Oct 2018  路  7Comments  路  Source: formium/formik

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!

Most helpful comment

You need to pass handleBlur or call setFieldTouched after blur on the input.

All 7 comments

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jaredpalmer picture jaredpalmer  路  3Comments

najisawas picture najisawas  路  3Comments

jaredpalmer picture jaredpalmer  路  3Comments

jordantrainor picture jordantrainor  路  3Comments

green-pickle picture green-pickle  路  3Comments