'React with Firebase - submitting Formik form data

I have a react app that uses Formik for forms and Cloud Firestore for the database.

I am trying to save the form data in Cloud Firestore. I get no errors in my console or react inspector tools, and when I press submit, I can see in the react inspect tool that the button goes to disabled and then enabled again, but the form doesn't clear the data and the data does not get sent to Cloud Firestore.

My handleSubmit function has:

handleSubmit = (formState, { resetForm }) => {
    // Now, you're getting form state here!
    const payload = {
        ...formState,
        fieldOfResearch: formState.fieldOfResearch.map(t => t.value),
        preregisterPlatform: formState.preregisterPlatform.value,
        resourceRequests: formState.resourceRequests.map(t => t.value),
        resourceOffers: formState.resourceOffers.map(t => t.value),
        ethicsIssue: formState.ethicsIssue.map(t => t.value),
        disclosureStatus: formState.disclosureStatus.value,
        createdAt: firebase.firestore.FieldValue.serverTimestamp()
      }
      console.log("formvalues", payload);

    fsDB
      .collection("project")
      .add(payload)
      .then(docRef => {
        console.log("docRef>>>", docRef);
        resetForm(initialValues);
      })
      .catch(error => {
        console.error("Error adding document: ", error);
      });
  };

My submit button has:

<div className="form-group">
                            <Button
                                variant="outline-primary"
                                type="submit"
                                id="ProjectId"
                                onClick={handleSubmit}
                                disabled={!dirty || isSubmitting}
                            >
                                Save
                            </Button>
                        </div>

The form is long - it has 39 questions, I can see from my Cloud Firestore data usage that I'm no where close to the limits for reads and writes. I don't know how to measure the size of my form submit data to know if the form data exceeds Cloud Firestore limits - is there a way to get Firestore to tell you if that's why the submit isn't working?

My console log to see the payload in the handleSubmit isn't running - so I think there must be another issue - I just can't find any information on what the problem might be.

Has anyone had an issue with long forms not posting to Cloud Firestore? If i keep the first 10 questions only, this form submits to the database.

I think I am well within my usage limits on firestore:

enter image description here

NEXT ATTEMPT

So, I took each of questions 11-39 out of the form and commented all of the Yup validations. I added the questions back one at a time and found that the form works and posts to firestore, until I uncommented the validations. They all pass - there are no errors. So - now I'm wondering if the time it costs to check them is counted by firestore for its process and maybe that's causing a time out? Is that possible? If so, is there any way to get an indication from Firestore that this is the problem? My validations are below.

I tried commenting and then uncommenting the validations in batches of 10. The form posts to firebase successfully if I comment all the validations from video down to the end. There are no errors in these validations. I just can't have them as well as successful posting to the database.

<Formik
            initialValues={initialValues}
            validationSchema={Yup.object().shape({
                title: Yup.string().required("Give your proposal a title"),
                subtitle: Yup.string().required("Now a subtitle"),
                fieldOfResearch: Yup.array().required("What is your field of research?"),
                disclosureStatus: Yup.string().nullable().required("Some projects are sensitive. Choose a disclosure setting."),
                overview: Yup.string().required("Outline your proposal"),
                objective: Yup.string().required("What is your objective?"),
                currentThinking: Yup.string().required("Outline the current thinking"),
                innovationStatement: Yup.string().required("If this proposal progresses previous research, what are the next steps that are being considered? If it is a paradigm shift, what has prompted it?"),
                influence: Yup.string().required("How is this proposal influenced by prevailing opinion?"),
                layperson: Yup.string().required("How would you describe this research to someone new to your field?"),
                elevator: Yup.string().required("Give it a try."),
                // video:
                resourcesConfirmation: Yup.string().required("Do you have access to research infrastructure you will need?"),
                participantPlan: Yup.string().required("Do you have a plan for how you will recruit participants for this research proposal? If your study does not require participants, then NA will do the job here."),
                resourceRequests: Yup.array().required('What sort of resources are you seeking?'),
                resourceOffers: Yup.array().required('What sort of resources will you bring to this project?'),
                technique: Yup.string().required("Ideally, this answer looks something close to 'Yes, because...' or a 'No, but this team is amazing and will master these techniques in no time, because...'"),
                pitfalls: Yup.string().required("If you've tried to look at this objectively, and can't see any pitfalls, then 'Not Applicable' will do here."),
                community: Yup.string().required("It can be a good idea to do this. If you do, you'll show sensitivity to the interests of others in your field and may open doors for potential collaborations and translation opportunities."),
                samplesize: Yup.string().required("These questions address research quality issues that funders are assessing in considering a proposal."),
                methodDescription: Yup.string().required("What approach will you take in this research?"),
                qualityControls: Yup.string().required("What controls will you put in place? These should address participants, comparators and any interventions."),
                sopAdoption: Yup.string().required("Describe at a summary level, any part of the Statement of Procedures that you have proposed that is noteworthy for reviewers."),
                participantNotification: Yup.string().required("Will you notify participants (if there are any) about the outcomes of this research? If so, describe how that will be done."),
                preregisterPlatform: Yup.string().nullable().required("Select preregistration intention"),
                teamOverview: Yup.string().required("Summarise the collective capabilities and experience of the team making this proposal"),
                proposalLead: Yup.string().required("Enter the name of the team leader"),
                indigenous: Yup.string().required("Either outline the contribution of indigenous team members or mark this field 'Not Applicable'"),
                teamSkillGap: Yup.string().required("Either outline the contribution of indigenous team members or mark this field 'Not Applicable'"),
                performanceIndicators: Yup.string().required("Either outline the performance indicators or mark this field 'Not Applicable'"),
                timeline: Yup.string().required("Either outline the milestones or mark this field 'Not Applicable'"),
                confirmationTeamLead: Yup.boolean().oneOf(
                    [true],
                    "Confirmation that you and each team member has reviewed each of the applicable policies is required"
                ),
                outcomeOverview: Yup.string().required("How might your study contribute to knowledge in the field?"),
                potentialApplications: Yup.string().required("Do you have any insight into potential applications for this research?"),
                potentialResearchAngles: Yup.string().required("Are there any tangential research questions that you think might follow from this study?"),
                budget: Yup.string().required("Attach a link to your project budget?"),
                ethicsIssue: Yup.array().required("Complete your ethics assessment"),
                ethicsManagementPlan: Yup.string().required("Add an ethics management plan, or if there are no issues, complete this field with 'Not Applicable'"),
                conflict: Yup.string().required("Are there any conflicts of interest?"),
                reproducibility: Yup.string().required("How will you approach reproducibility?"),
            })}


Solution 1:[1]

I'm betting my money on that the object you send to firestore has some fields in (11-39 question) has undefined or null value in it.

Try clear those undefined value before send to firestore, because Firestore won't save undefined value and will throw error.

// You can send this to firestore.
const payload = {
  a: 1,
  b: 'text value',
  c: [{ id: 432 }]
}

// You canNOT send this to firestore.
const payload = {
  a: 1,
  b: undefined,
  c: [{ id: 432 }]
}

Solution 2:[2]

My console log to see the payload in the handleSubmit isn't running...
  • This is important. This means that the problem is in Formik. Not in Firebase.

  • Comment the fsDB part. Wrap the handleSubmit block in a try/catch and console.log the try part and console.error the catch part. Also, add a console.log before the payload declaration. The information you get should explain what causes the problem.

In order to debug, I mean replace handleSubmit with:

handleSubmit = (formState, { resetForm }) => {
    try {
        console.log('TRY');
        // Now, you're getting form state here!
        const payload = {
        ...formState,
        fieldOfResearch: formState.fieldOfResearch.map(t => t.value),
        preregisterPlatform: formState.preregisterPlatform.value,
        resourceRequests: formState.resourceRequests.map(t => t.value),
        resourceOffers: formState.resourceOffers.map(t => t.value),
        ethicsIssue: formState.ethicsIssue.map(t => t.value),
        disclosureStatus: formState.disclosureStatus.value,
        createdAt: firebase.firestore.FieldValue.serverTimestamp()
          }
          console.log("formvalues", payload);

        /*
        fsDB
          .collection("project")
          .add(payload)
          .then(docRef => {
        console.log("docRef>>>", docRef);
        resetForm(initialValues);
          })
          .catch(error => {
        console.error("Error adding document: ", error);
          });
        */

    } catch (reason) {
           console.error('CATCH', reason)
    }
  };

Solution 3:[3]

Possibly your validation schema is the issue. Have you tried removing the shape bit from the start, I do not see them using it like that in the Formik docs they just use Yup.object({validation here})

validationSchema={Yup.object({
                title: Yup.string().required("Give your proposal a title"),
                subtitle: Yup.string().required("Now a subtitle"),
                fieldOfResearch: Yup.array().required("What is your field of research?"),
                disclosureStatus: Yup.string().nullable().required("Some projects are sensitive. Choose a disclosure setting."),
                overview: Yup.string().required("Outline your proposal"),
                objective: Yup.string().required("What is your objective?"),
                currentThinking: Yup.string().required("Outline the current thinking"),
                innovationStatement: Yup.string().required("If this proposal progresses previous research, what are the next steps that are being considered? If it is a paradigm shift, what has prompted it?"),
                influence: Yup.string().required("How is this proposal influenced by prevailing opinion?"),
                layperson: Yup.string().required("How would you describe this research to someone new to your field?"),
                elevator: Yup.string().required("Give it a try."),
                // video:
                resourcesConfirmation: Yup.string().required("Do you have access to research infrastructure you will need?"),
                participantPlan: Yup.string().required("Do you have a plan for how you will recruit participants for this research proposal? If your study does not require participants, then NA will do the job here."),
                resourceRequests: Yup.array().required('What sort of resources are you seeking?'),
                resourceOffers: Yup.array().required('What sort of resources will you bring to this project?'),
                technique: Yup.string().required("Ideally, this answer looks something close to 'Yes, because...' or a 'No, but this team is amazing and will master these techniques in no time, because...'"),
                pitfalls: Yup.string().required("If you've tried to look at this objectively, and can't see any pitfalls, then 'Not Applicable' will do here."),
                community: Yup.string().required("It can be a good idea to do this. If you do, you'll show sensitivity to the interests of others in your field and may open doors for potential collaborations and translation opportunities."),
                samplesize: Yup.string().required("These questions address research quality issues that funders are assessing in considering a proposal."),
                methodDescription: Yup.string().required("What approach will you take in this research?"),
                qualityControls: Yup.string().required("What controls will you put in place? These should address participants, comparators and any interventions."),
                sopAdoption: Yup.string().required("Describe at a summary level, any part of the Statement of Procedures that you have proposed that is noteworthy for reviewers."),
                participantNotification: Yup.string().required("Will you notify participants (if there are any) about the outcomes of this research? If so, describe how that will be done."),
                preregisterPlatform: Yup.string().nullable().required("Select preregistration intention"),
                teamOverview: Yup.string().required("Summarise the collective capabilities and experience of the team making this proposal"),
                proposalLead: Yup.string().required("Enter the name of the team leader"),
                indigenous: Yup.string().required("Either outline the contribution of indigenous team members or mark this field 'Not Applicable'"),
                teamSkillGap: Yup.string().required("Either outline the contribution of indigenous team members or mark this field 'Not Applicable'"),
                performanceIndicators: Yup.string().required("Either outline the performance indicators or mark this field 'Not Applicable'"),
                timeline: Yup.string().required("Either outline the milestones or mark this field 'Not Applicable'"),
                confirmationTeamLead: Yup.boolean().oneOf(
                    [true],
                    "Confirmation that you and each team member has reviewed each of the applicable policies is required"
                ),
                outcomeOverview: Yup.string().required("How might your study contribute to knowledge in the field?"),
                potentialApplications: Yup.string().required("Do you have any insight into potential applications for this research?"),
                potentialResearchAngles: Yup.string().required("Are there any tangential research questions that you think might follow from this study?"),
                budget: Yup.string().required("Attach a link to your project budget?"),
                ethicsIssue: Yup.array().required("Complete your ethics assessment"),
                ethicsManagementPlan: Yup.string().required("Add an ethics management plan, or if there are no issues, complete this field with 'Not Applicable'"),
                conflict: Yup.string().required("Are there any conflicts of interest?"),
                reproducibility: Yup.string().required("How will you approach reproducibility?")
            })}

Solution 4:[4]

There is a param in Formik as errors. You can access it via

<Formik>
  (handleSubmit,errors,touched){
     console.log(errors);
     return (<React.Fragement>
      // Put other elements in here
      </React.Fragement>);
  }
</Formik>

After submitting the code you can see the errors which are occurred in your form. And use Formik like https://codesandbox.io/s/zkrk5yldz

And it is a good practice to use the validation schema out of the function as a separate object. Because it does not need to rebuild again and again. (

Solution 5:[5]

You've set your handleSubmit function as the onClick handler of the button. Therefore when you click on the button, handleSubmit get passed the event object and not the formik variables.

In order for you handleSubmit function to be called correctly, you need to:

  1. Pass handleSubmit it to the onSubmit prop of the Formik component.
  2. Pass the submitForm function provided by formik as the onClick handler of your button.

You'll find more details in the formik documentation about submitting the form

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Doppio
Solution 2
Solution 3 AlexanderKaran
Solution 4 Kaveesha Dinamidu
Solution 5 Araelath