reactjsformikdynamic-forms

React Formik FieldArray remove and push does not work


I wanted to have a dynamic form, so I followed this video (https://www.youtube.com/watch?v=me1kY_uFe5k) to utilize Formik remove and push method.

Now the browser is able to render all the data, but when I click on the "Delete" button or the "Add" button, nothing happened. There are also no error message so I did not know how to debug/fix it.

Note: When I review the tutorial video, I found the author used "values" (as default Props) to retrieve data. I did not go this way. Could it be the root cause? What is the use case of "values"? The video author used "values" but he did not explain why it was used.

function CreateTestSuite3() {

    const initialValues = {
        testSuite: { 
            tsId: 0,
            tsName: "",
            tsDescription: "",
            testCases: [ 
                {
                testCaseNumber: 0,
                testCaseName: "",
                testCaseEnvironment: "",
                testCaseSQL: ""
                }
            ]
        }
    }; 

    const onSubmit = (data) => { 
        console.log("this is form data: ", data); 
        axios.post("http://localhost:8080/TestSuite/CreateTestSuite", data)
            .then((response) => {
                console.log("Form Submitted");
        })
    };

    return (
        <div className="CreateTestSuite">
            <Formik initialValues={initialValues} onSubmit={onSubmit}>
                <Form className="formContainer">
                    <label>Test Suite Id: </label>
                    <ErrorMessage name="tsId" component="span" />
                    <Field autoComplete="off" name="testSuite.tsId" placeholder="tsId" />

                    <label>Test Suite Name: </label>
                    <ErrorMessage name="tsName" component="span" />
                    <Field autoComplete="off" name="testSuite.tsName" placeholder="tsName" />

                    <label>Test Suite Description: </label>
                    <ErrorMessage name="tsDescription" component="span" />
                    <Field autoComplete="off" name="testSuite.tsDescription" placeholder="tsDescription" />

                    <FieldArray name="testSuite.testCases">
                        {({push, remove, }) => (
                            <>
                            {initialValues.testSuite.testCases.map((TestCase, index) => (
                                    <div key={index}>

                                        <label>Test Case Number: </label>
                                        <Field name={`TestCase.${index}.testCaseNumber`} placeholder="testCaseNumber" ></Field>

                                        <label>Test Case Name: </label>
                                        <Field name={`TestCase.${index}.testCaseName`} placeholder="testCaseName" ></Field>

                                        <label>Test Case Environment: </label>
                                        <Field name={`TestCase[${index}].testCaseEnvironment`} placeholder="testCaseEnvironment" ></Field>

                                        <label>Test Case SQL: </label>
                                        <Field name={`TestCase[${index}].testCaseSQL`} placeholder="testCaseSQL" ></Field>

                                        <button type="button" onClick={() => remove(index)} >Delete</button>
                                    </div>
                             ))}
                                
                                <button type="button" onClick={() => push({ testCaseNumber: 0, testCaseName: "", testCaseEnvironment: "", testCaseSQL: "" })}>Add Test Case</button>
                            </>
                        )}
                    </FieldArray>

                    <button type="submit">Create Test Suite</button>

                </Form>
            </Formik>
        </div>
    )
}

Solution

  • Add and remove is not working since your rendering using the initial values and not the updated values. Please refer the below code.

      <Formik initialValues={initialValues} onSubmit={onSubmit}>
            {(formik) => {
              const { values } = formik;
              return (
                <Form className="formContainer">
                  <label>Test Suite Id: </label>
                  <Field
                    autoComplete="off"
                    name="testSuite.tsId"
                    placeholder="tsId"
                  />
    
                  <label>Test Suite Name: </label>
                  <Field
                    autoComplete="off"
                    name="testSuite.tsName"
                    placeholder="tsName"
                  />
    
                  <label>Test Suite Description: </label>
                  <Field
                    autoComplete="off"
                    name="testSuite.tsDescription"
                    placeholder="tsDescription"
                  />
    
                  <FieldArray
                    type="testSuite.testCases"
                    name="testSuite.testCases"
                    id="testSuite.testCases"
                    value={values.testSuite.testCases}
                    render={(arrayHelpers) => (
                      <div className="formContainer">
                        {values.testSuite.testCases.map((TestCase, index) => (
                          <div className="formContainer" key={index}>
                            <label>Test Case Number: </label>
                            <Field
                              name={`TestCase.${index}.testCaseNumber`}
                              placeholder="testCaseNumber"
                            ></Field>
    
                            <label>Test Case Name: </label>
                            <Field
                              name={`TestCase.${index}.testCaseName`}
                              placeholder="testCaseName"
                            ></Field>
    
                            <label>Test Case Environment: </label>
                            <Field
                              name={`TestCase[${index}].testCaseEnvironment`}
                              placeholder="testCaseEnvironment"
                            ></Field>
    
                            <label>Test Case SQL: </label>
                            <Field
                              name={`TestCase[${index}].testCaseSQL`}
                              placeholder="testCaseSQL"
                            ></Field>
    
                            <button
                              type="button"
                              onClick={() => arrayHelpers.remove(index)}
                            >
                              Delete
                            </button>
                          </div>
                        ))}
    
                        <button
                          type="button"
                          onClick={() => {
                            console.log("hit");
                            arrayHelpers.insert({
                              testCaseNumber: 0,
                              testCaseName: "",
                              testCaseEnvironment: "",
                              testCaseSQL: ""
                            });
                          }}
                        >
                          Add Test Case
                        </button>
                      </div>
                    )}
                  />
    
                  <button type="submit">Create Test Suite</button>
                </Form>
              );
            }}
          </Formik>
    

    Code Sandbox: https://codesandbox.io/s/frosty-platform-ty83no?file=/src/App.js:527-3738