简体   繁体   English

与 Firebase 反应 - 提交 Formik 表单数据

[英]React with Firebase - submitting Formik form data

I have a react app that uses Formik for forms and Cloud Firestore for the database.我有一个反应应用程序,它使用 Formik 作为 forms 和 Cloud Firestore 作为数据库。

I am trying to save the form data in Cloud Firestore.我正在尝试将表单数据保存在 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.我在控制台或反应检查器工具中没有收到任何错误,当我按下提交时,我可以在反应检查工具中看到按钮被禁用然后再次启用,但表单没有清除数据,数据确实如此不会发送到 Cloud Firestore。

My handleSubmit function has:我的 handleSubmit function 有:

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.表格很长 - 它有 39 个问题,我可以从我的 Cloud Firestore 数据使用情况中看出我离读写限制还差得很远。 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?我不知道如何测量我的表单提交数据的大小以了解表单数据是否超过 Cloud Firestore 限制 - 有没有办法让 Firestore 告诉您这是否就是提交不起作用的原因?

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.我的控制台日志查看 handleSubmit 中的有效载荷没有运行 - 所以我认为一定有另一个问题 - 我只是找不到任何关于问题可能是什么的信息。

Has anyone had an issue with long forms not posting to Cloud Firestore?有没有人遇到长 forms 没有发布到 Cloud Firestore 的问题? If i keep the first 10 questions only, this form submits to the database.如果我只保留前 10 个问题,此表单将提交给数据库。

I think I am well within my usage limits on firestore:我认为我在 firestore 的使用限制范围内:

在此处输入图像描述

NEXT ATTEMPT下一次尝试

So, I took each of questions 11-39 out of the form and commented all of the Yup validations.因此,我从表格中取出了第 11-39 个问题,并对所有 Yup 验证进行了评论。 I added the questions back one at a time and found that the form works and posts to firestore, until I uncommented the validations.我一次一个地添加问题,发现表单有效并发布到 firestore,直到我取消对验证的注释。 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?所以 - 现在我想知道检查它们所花费的时间是否被 firestore 计算在它的过程中,也许这会导致超时? Is that possible?那可能吗? If so, is there any way to get an indication from Firestore that this is the problem?如果是这样,是否有任何方法可以从 Firestore 获得问题所在的指示? 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.我尝试对验证进行评论,然后以 10 个为一组取消评论。如果我对从视频到最后的所有验证进行评论,则表单会成功发布到 firebase。 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?"),
            })}

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.我打赌你发送到 firestore 的对象在(11-39 问题)中有一些字段有undefinednull值。

Try clear those undefined value before send to firestore, because Firestore won't save undefined value and will throw error.在发送到 firestore 之前尝试清除那些未定义的值,因为 Firestore 不会保存undefined值并且会抛出错误。

// 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 }]
}
My console log to see the payload in the handleSubmit isn't running...
  • This is important.这个很重要。 This means that the problem is in Formik.这意味着问题出在 Formik 中。 Not in Firebase.不在 Firebase 中。

  • Comment the fsDB part.注释 fsDB 部分。 Wrap the handleSubmit block in a try/catch and console.log the try part and console.error the catch part.将 handleSubmit 块包装在 try/catch 和 console.log 的 try 部分和 console.error 的 catch 部分。 Also, add a console.log before the payload declaration.此外,在有效负载声明之前添加一个 console.log。 The information you get should explain what causes the problem.您获得的信息应解释导致问题的原因。

In order to debug, I mean replace handleSubmit with:为了调试,我的意思是将 handleSubmit 替换为:

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)
    }
  };

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})您是否尝试从一开始就删除形状位,我没有看到他们像在 Formik 文档中那样使用它,他们只是使用 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?")
            })}

There is a param in Formik as errors. Formik 中有一个参数作为错误。 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并像https://codesandbox.io/s/zkrk5yldz一样使用 Formik

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.因为它不需要一次又一次地重建。 ( (

You've set your handleSubmit function as the onClick handler of the button.您已将handleSubmit function 设置为按钮的onClick处理程序。 Therefore when you click on the button, handleSubmit get passed the event object and not the formik variables.因此,当您单击按钮时, handleSubmit将传递事件 object 而不是 formik 变量。

In order for you handleSubmit function to be called correctly, you need to:为了正确调用handleSubmit function,您需要:

  1. Pass handleSubmit it to the onSubmit prop of the Formik component.handleSubmit传递给Formik组件的onSubmit道具。
  2. Pass the submitForm function provided by formik as the onClick handler of your button.将 formik 提供的submitForm function 作为按钮的onClick处理程序传递。

You'll find more details in the formik documentation about submitting the form您将在 formik 文档中找到有关提交表单的更多详细信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM