Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Formik form not updating fields upon edit

Tags:

reactjs

formik

I've been trying to rewrite my beginner form in React to use Formik. I've gotten to the state that the form is being rendered, however, for some reason, I can't update the fields. It's clear that I made a mistake somewhere that prevents Formik from updating the state. What am I missing?

An example form component:

export const TextBox: React.SFC<FieldProps<any> & CustomFormElementProps> = ({
    field, // { name, value, onChange, onBlur }
    form: { touched, errors }, 
    loading,
    ...props
}) => (
        <div className="row form-group" key={field.name}>
            <label className="col-sm-2 control-label">
                <ReactPlaceholder showLoadingAnimation ready={!loading} type="text" rows={1} className="control-label">
                    {props.label}
                </ReactPlaceholder>
            </label>
            <div className="col-sm-10">
                <ReactPlaceholder showLoadingAnimation ready={!loading} type="text" rows={1} className="form-control">
                    <input type="text"
                        disabled={props.disabled}
                        className="form-control"
                        id={field.name}
                        onChange={field.onChange}
                        onBlur={field.onBlur} {...props} />
                    {touched[field.name] && errors[field.name] && <span className="text-danger">{errors[field.name]}</span>}
                </ReactPlaceholder>
            </div>
        </div>
    );

The form is initialized in another component (which acts as a page template for the website);

renderFormElements() {
        var formFields = this.props.detailsElements.map((item) => {
            switch (item.type) {
                case FormElementType.TextLine:
                    return <TextLine
                        name={item.name}
                        label={item.label}
                        disabled={!this.state.editMode}
                        loading={item.loading}
                        value={item.defaultValue}
                        key={'TextBox_' + item.name}
                    />
                case FormElementType.TextBox:
                    return <Field
                        type="text"
                        name={item.name}
                        label={item.label}
                        component={InputElements.TextBox}
                        disabled={!this.state.editMode}
                        loading={item.loading}
                        value={item.defaultValue}
                        key={'TextBox_' + item.name}
                    />
                case FormElementType.DropDown:
                    return <Field
                        name={item.name}
                        label={item.label}
                        component={InputElements.DropDown}
                        disabled={!this.state.editMode}
                        loading={item.loading}
                        value={item.defaultValue}
                        options={item.options}
                        key={'DropDown_' + item.name}
                    />
                case FormElementType.RadioGroup:
                    return <Field
                        type="radio"
                        name={item.name}
                        label={item.label}
                        component={InputElements.RadioGroup}
                        disabled={!this.state.editMode}
                        loading={item.loading}
                        value={item.defaultValue}
                        options={item.options}
                        key={'RadioGroup' + item.name}
                    />
                }
        });

        var initialValues:{ [k: string]: any } = {};
        this.props.detailsElements.map((item) => {
            initialValues[item.name] = item.defaultValue;
        })
        console.log(initialValues);

        var formSection =
            (<Formik initialValues={initialValues} onSubmit={(values, actions) => {
                setTimeout(() => {
                    alert(JSON.stringify(values, null, 2))
                    actions.setSubmitting(false)
                }, 1000)
            }}>
                <Form key="mainForm">
                    {formFields}
                </Form>
            </Formik>)

        return formSection;

I was assuming that the onChange event handler was taken care of by Formik, and that, if I didn't want to do special stuff, I did not need to provide anything to this. What am I missing here?

Thanks!

like image 844
Mortana Avatar asked Jul 18 '18 07:07

Mortana


People also ask

How do I update my Formik data?

You can enable enableReinitialize property of Formik to update the field.

Is Formik controlled or uncontrolled?

This is a controlled component. All the values, i.e., initialValues, are handled by Formik. In the above component, we have used Formik, Field and ErrorMessage components. These are similar to the normal input elements present inside the form element.

How do you reset Formik fields?

If you want to reset the selected value after the form is submitted, you need to provide a controlled value for the Select component. The Formik Field component provides the value in the props object, so you can use it.

How does touched work in Formik?

The keys of touched are the field names, and the values of touched are booleans true / false . To take advantage of touched , we pass formik.handleBlur to each input's onBlur prop. This function works similarly to formik.handleChange in that it uses the name attribute to figure out which field to update.


1 Answers

your formFields function gets all of Formik props goodies. it contains handleChange - use this handler as your on change.

Also, make sure the field "id" is the same as the values key.

const {
  values,
  touched,
  errors,
  dirty,
  isSubmitting,
  handleChange,
  handleBlur,
  handleSubmit,
} = this.props;
<FormControl
      id="username"
      required
      placeholder="Enter Username"
      value={values.username}
      error={touched.username && errors.username}
      onChange={handleChange}
      onBlur={handleBlur}
    />
like image 178
Idan Hen Avatar answered Nov 15 '22 11:11

Idan Hen