Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why do I need to manually call setFieldTouched? #955

Closed
cjones26 opened this issue Oct 3, 2018 · 7 comments
Closed

Why do I need to manually call setFieldTouched? #955

cjones26 opened this issue Oct 3, 2018 · 7 comments

Comments

@cjones26
Copy link

cjones26 commented Oct 3, 2018

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!

@Saifadin
Copy link
Contributor

Saifadin commented Oct 3, 2018

Have you tried using props.form.touched[name] to check for this information?

@cjones26
Copy link
Author

cjones26 commented Oct 4, 2018

@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.

@Saifadin
Copy link
Contributor

Saifadin commented Oct 4, 2018

Can you provide the place, where you call that Component from? Basically the <Formik> container

@cjones26
Copy link
Author

cjones26 commented Oct 4, 2018

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>
);

@Saifadin
Copy link
Contributor

Saifadin commented Oct 4, 2018

It seems to work for me 😅, can you recreate it in codesandbox and provide a url.

@cjones26
Copy link
Author

cjones26 commented Oct 4, 2018

@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..?

@jaredpalmer
Copy link
Owner

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants