How to define setFieldValue in React
Asked Answered
O

4

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?

Omarr answered 7/9, 2020 at 9:9 Comment(0)
B
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>
Buss answered 7/9, 2020 at 12:50 Comment(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 inputOmarr
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) }, also, <Field/> contains the onBlur function which causes the on blur warning on the console.Buss
it works! you could update your answer so I can accept itOmarr
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.Eamon
C
2

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

Christcrossrow answered 8/7, 2021 at 19:7 Comment(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.Chiclayo
C
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>;
Considerable answered 7/9, 2020 at 9:13 Comment(4)
so the dropdown gets opened when I click on it, I select one option from the dropdown but it is not selected, it still shows the value from the placeholderOmarr
added, unfortunately it's same resultOmarr
how about this way?Considerable
still not working but I think it is closer. do you have one minute to join a google meeting where I can share my screen? meet.google.com/exw-zrrn-qadOmarr
C
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 });
 }
Coniology answered 7/9, 2020 at 9:46 Comment(4)
and if it put it like: ` onChange={e => this.onChange('industry', e.target.value) }` it crashes when I click on options from dropdownOmarr
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 constructorConiology
in that case ESLint says that e is not definedOmarr
okay, do this onChange={this.onChange('industry')} and in onChange() you must pass as params like this onChange(e,name)Coniology

© 2022 - 2024 — McMap. All rights reserved.