Search code examples
reactjsmaterial-uiformikformik-material-ui

set value for <TextField/> through Formik <Field/> using custom component in <FieldArray/>


I am trying to set default value of a dynamic form through the use of index of map, below is the code snippet:

<Formik
                initialValues={initialInputField}
                onSubmit={(data) => handleSubmitForm(data)}
                // validationSchema={validationSchema}
            >
                {({ values, handleSubmit, isSubmitting }) => (
                    <Form onSubmit={handleSubmit}>
                        <FieldArray name="processes">
                            {({ push, remove }) => {
                                return (
                                    <div>
                                        <Button
                                            onClick={() => push(initialInputField.processes[0])}
                                            className={classes.generateButton}
                                            variant="outlined"
                                        >
                                            Add Process
                                        </Button>
                                        <div className={classes.root}>
                                            {map(values.processes, (data, index: number) => {
                                                return (
                                                    <div key={index}>
                                                        <Field
                                                            label="Process"
                                                            value={index} // add index as process value
                                                            name={`processes[${index}].process`}
                                                            component={Input}
                                                        />
                                                        <IconButton onClick={() => remove(index)}>
                                                            <RemoveIcon />
                                                        </IconButton>
                                                    </div>
                                                );
                                            })}
                                        </div>
                                    </div>
                                );
                            }}
                        </FieldArray>
                        <Button
                            className={classes.generateButton}
                            variant="outlined"
                            type="submit"
                        >
                            Generate
                        </Button>
                    </Form>
                )}
            </Formik>

this is the code snippet for my custom component:

const Input = ({ field, value, label, form: { errors } }: any) => {
    return (
        <>
            <TextField {...field} label={label} value={value} variant="filled" />
        </>
    );
};

the problem is that when I submit the form, all the value of process remained to be "" which is my initial value although the form is already changed

example: (processes are filled in with correct value)

enter image description here

(processes are still empty after i submited to form)

enter image description here


Solution

  • I think it is because you are passing the "value" prop to the Input Component and using it. The input will show it as the index, but you have done nothing to change the formik state.

    You are also prop spreading "field..." onto Input, which also has "value". You want the field.value not your value prop, so you can actually reflect what formik has in state in your Input.

    I think it would be a much better practice and less painful, to just create this data up front and pipe it into the formik initialValues props.

    Otherwise, you could handle it in the init of your Input component, pass a defaultValue prop to it (index), use the form.setFieldValue (form is prop given by Field) to update formik state with defaultValue if no field.value is present.