5

I'm using Formik for validating the fields before creating an entity. There is a Select which opens a dropdown and the user must choose one option from there.

I get an error saying that setFieldValue is not defined but where I've researched before I didn't find any definition of this method, it is just used like that so I don't know why is this happening.

This is my code:

import React from 'react';
import { Formik, Form, Field } from 'formik';
import { Button, Label, Grid } from 'semantic-ui-react';
import * as Yup from 'yup';

class CreateCompanyForm extends React.PureComponent {
  constructor(props) {
    super(props);

    this.state = {
      industry: '',
    };
  }

  onChange = (e, { name, value }) => {
    this.setState({ [name]: value });
  };

  handleSubmit = values => {
    // ...
  };

  render() {
    const nameOptions = [
      { text: 'Services', value: 'Services' },
      { text: 'Retail', value: 'Retail' },
    ];

    const initialValues = {
      industry: '',
    };
    const requiredErrorMessage = 'This field is required';
    const validationSchema = Yup.object({
      industry: Yup.string().required(requiredErrorMessage),
    });
    return (
      <div>
        <div>
          <Button type="submit" form="amazing">
            Create company
          </Button>
        </div>

        <Formik
          htmlFor="amazing"
          initialValues={initialValues}
          validationSchema={validationSchema}
          onSubmit={values => this.handleSubmit(values)}>
          {({ errors, touched }) => (
            <Form id="amazing">
              <Grid>
                <Grid.Column>
                  <Label>Industry</Label>
                  <Field
                    name="industry"
                    as={Select}
                    options={nameOptions}
                    placeholder="select an industry"
                    onChange={e => setFieldValue('industry', e.target.value)}  // here it is
                  />

                  <div>
                    {touched.industry && errors.industry
                      ? errors.industry
                      : null}
                  </div>
                </Grid.Column>
              </Grid>
            </Form>
          )}
        </Formik>
      </div>
    );
  }
}

The error says: 'setFieldValue' is not defined no-undef - it is from ESLint. How can be this solved?

Leo Messi
  • 5,157
  • 14
  • 63
  • 125

4 Answers4

12

setFieldValue is accessible as one of the props in Formik.

I tried it on CodeSandbox, apparently, the first parameter in the onChange prop returns the event handler while the second one returns the value selected onChange={(e, selected) => setFieldValue("industry", selected.value) }

    <Formik
      htmlFor="amazing"
      initialValues={initialValues}
      validationSchema={validationSchema}
      onSubmit={(values) => this.handleSubmit(values)}
    >
      {({ errors, touched, setFieldValue }) => (
        //define setFieldValue
        <Form id="amazing">
          <Grid>
            <Grid.Column>
              <Label>Industry</Label>
              <Field
                id="industry" // remove onBlur warning
                name="industry"
                as={Select}
                options={nameOptions}
                placeholder="select an industry"
                onChange={(e, selected) =>
                  setFieldValue("industry", selected.value)
                }
              />

              <div>
                {touched.industry && errors.industry
                  ? errors.industry
                  : null}
              </div>
            </Grid.Column>
          </Grid>
        </Form>
      )}
    </Formik>
diane
  • 171
  • 4
  • So I changed it like this, when I click the submit button nothing happens, just in console I get this warning: Warning: Formik called `handleBlur`, but you forgot to pass an `id` or `name` attribute to your input – Leo Messi Sep 07 '20 at 12:55
  • 1
    I tried it on [CodeSandbox](https://codesandbox.io/s/formik-validation-select-2khqg?file=/src/App.js), apparently, the first parameter in the onChange prop returns the event handler while the second one returns the value selected `onChange={(e, selected) => setFieldValue("industry", selected.value) }`, also, contains the onBlur function which causes the on blur warning on the console. – diane Sep 07 '20 at 13:49
  • it works! you could update your answer so I can accept it – Leo Messi Sep 07 '20 at 14:07
  • Facing this error==> Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string. – Hassan Ali Shahzad Mar 14 '21 at 08:53
2

try calling it using this structure onChange = {v => formik.setFieldValue('field', v)}

Sandy
  • 21
  • 1
  • There has already been an approved answer to this question answered quite a few months ago. If your looking to get your rep up you should look at latest questions. – Richard Hpa Jul 08 '21 at 21:38
1
<Formik
  htmlFor="amazing"
  initialValues={initialValues}
  value={{industry:this.state.industry}}
  validationSchema={validationSchema}
  onSubmit={(values) => this.handleSubmit(values)}
>
  {({ errors, touched }) => (
    <Form id="amazing">
      <Grid>
        <Grid.Column>
          <Label>Industry</Label>
          <Field
            name="industry"
            as={Select}
            options={nameOptions}
            placeholder="select an industry"
            onChange={(e) =>
              this.setState({
                industry: e.target.value,
              })
            } // here it is
          />

          <div>
            {touched.industry && errors.industry ? errors.industry : null}
          </div>
        </Grid.Column>
      </Grid>
    </Form>
  )}
</Formik>;
Liu Lei
  • 1,256
  • 1
  • 9
  • 18
1

Replace your onChange by onChange={this.onChange('industry', e.target.value)} and in your constructor add this line this.onChange = this.onChange.bind(this). your onChange methode will be:

onChange(e, { name, value }){
   this.setState({ [name]: value });
 }
Mas dem
  • 97
  • 1
  • 1
  • and if it put it like: ` onChange={e => this.onChange('industry', e.target.value) }` it crashes when I click on options from dropdown – Leo Messi Sep 07 '20 at 10:04
  • not like this `onChange={e => this.onChange('industry', e.target.value) }` but rather this `onChange={this.onChange('industry', e.target.value)}` and bind it in your constructor – Mas dem Sep 07 '20 at 10:26
  • in that case ESLint says that e is not defined – Leo Messi Sep 07 '20 at 10:30
  • okay, do this `onChange={this.onChange('industry')}` and in `onChange()` you must pass as params like this `onChange(e,name)` – Mas dem Sep 07 '20 at 11:08