使用Gatsby提交表单时使用Netlify 404

时间:2020-04-17 11:55:27

标签: reactjs gatsby netlify react-hook-form

我有一个表单组件,可以在网站上重复使用,该组件将表单名称作为参数。该网站是使用Gatsby构建的,并托管在Netlify上。

每当我尝试填写表单并按Submit按钮时,控制台中都会出现404错误,并且表单没有提交,但是我可以在Netlify Forms中看到所有表单。我不确定我的错误在哪里,当我在chrome中检查时,发现data-netlify="true"属性不在前端,但是在代码中存在。

我的功能

import React, { useState } from "react"
import { useForm } from "react-hook-form"

function encode(data) {
  return Object.keys(data)
    .map((key) => encodeURIComponent(key) + "=" + encodeURIComponent(data[key]))
    .join("&")
}

const ContactForm = ({ data, name, type, index }) => {
  const { register, handleSubmit, errors, reset } = useForm({
    mode: "onBlur",

  })

  const [feedbackState, setFeedbackState] = useState(null)
  const [errorState, setErrorState] = useState(null)
  const [requestType, setRequestType] = useState(null)
  const [state, setState] = useState({})

  const handleChange = (e) => {
    {
      setState({ ...state, [e.target.name]: e.target.value })
    }
  }
  const onSubmit = (data, e) => {
    e.preventDefault()
    fetch("/", {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: encode({
        "form-name": {name},
        ...state,
      }),
    })
      .then((response) => {
        setFeedbackState(true)
        reset()
      })
      .catch((error) => {
        setErrorState(true)
      })
  }

我的表单:

if (feedbackState) {
    return (
      <div className="callout success">
        <h3>Vad roligt att du är intresserad av våra produkter!</h3>
        <p>
          Vi kommer höra av oss inom kort till {state.fName} {state.lName} på{" "}
          {state.email}.
        </p>
      </div>
    )
  } else {
    return (
      <>
        {console.log("form navn er, ", name)}
        <form
          id="contactMe"
          onSubmit={handleSubmit(onSubmit)}
          name={name}
          method="post"
          data-netlify="true"
          data-netlify-honeypot="bot-field"
        >
          <input type="hidden" name="form-name" value={name} />
          <div hidden>
            <label>
              Don’t fill this out:{' '}
              <input name="bot-field" onChange={handleChange} />
            </label>
          </div>          <fieldset class="grid-x grid-margin-x">
            <legend class="cell">
              <h3>{data.formTitle}</h3>
            </legend>

            <div class="cell medium-6">
              <div class="form-field">
                <label htmlFor="fName">
                  {data.firstName}
                  <span
                    id="error-required-field"
                    style={{
                      display:
                        errors.fName && errors.fName.type === "required"
                          ? "block"
                          : "none",
                    }}
                  >
                    {data.firstNameRequired}
                  </span>
                  <span style={{ display: "none" }}>
                    <label>Request type: </label>
                    <input
                      type="text"
                      id="requestType"
                      onChange={handleChange}
                      name="requestType"
                      value={type}
                      ref={register({ required: true })}
                    />
                  </span>
                </label> ....more form values

在这里可以看到我的表单的示例,我尝试了console.logging表单中的所有属性,并可以看到它们

<ContactForm
    name="Tilgjenlighetsanalys"
    data={data.auditsForm}
    type="Liten analys"
  />

关于我在做什么错的任何想法?

编辑:提交表单时,我将在chrome网络标签中看到表单名称设置为[object Object]而不是实际表单名称的情况 screenshot ov chrome dev tools network tab showing form name as object Object

2 个答案:

答案 0 :(得分:0)

结果证明,我不能像以前那样传递数据,Chrome开发人员工具将表单名称显示为[Object,object],而不是我在console.logging时输入的名称。为了解决这个问题,我对名称进行了字符串化。

此行解决了我的问题:

  const formName = JSON.stringify(name);

然后以我的形式将值作为普通变量传递

  <input type="hidden" name="form-name" value={formName} />

编辑:此方法有一个主要缺陷,所有名称现在都用引号引起来。如果有更好的方法,请发布。

答案 1 :(得分:0)

只需补充一点,即在将应用程序部署到netlify之后必须完成表单测试。本地测试将为您提供404

如果您部署并且仍然出现错误,请删除验证码(如果您保留验证码代码,并且验证码的设置不正确,则会收到303错误-我建议删除验证码以确保您的表格可以正常工作,然后您可以解决验证码问题,因为他们有很多有关如何正确添加验证码的文章-以下是我在生产中正在使用的gatsby / netlify表格

import React, { useState } from 'react';
import styled from 'styled-components';
import { navigate } from 'gatsby';
import SEO from '../components/SEO';

const StyledContactPage = styled.section`
  display: grid;
  place-items: center;
  min-height: calc(100vh - 12rem);
  article {
    background: var(--clr-concrete-white);
    border-radius: var(--radius);
    text-align: center;
    box-shadow: var(--light-shadow);
    transition: var(--transition);
    width: 90vw;
    max-width: 35rem;
    &:hover {
      box-shadow: var(--dark-shadow);
    }
    h3 {
      padding-top: 1.25rem;
      color: var(--clr-primary);
    }
    .form-group {
      padding: 1rem 1.5rem;
    }
    .form-control {
      display: block;
      width: 100%;
      padding: 0.75rem 1rem;
      border: none;
      margin-bottom: 1.25rem;
      background: var(clr-codgray-black);
      /* background: red; */
      border-radius: var(--radius);
      text-transform: uppercase;
      letter-spacing: var(--spacing);
      &::placeholder {
        font-family: var(--ff-primary);
        color: var(--clr-jewel-green);
        text-transform: uppercase;
        letter-spacing: var(--spacing);
      }
    }
    .submit-btn {
      display: block;
      width: 100%;
      padding: 1rem;
      border-bottom-left-radius: var(--radius);
      border-bottom-right-radius: var(--radius);
      border-top-right-radius: 0;
      border-top-left-radius: 0;
    }
  }
`;

const ContactPage = () => {
  const [formState, setFormState] = useState({
    firstName: '',
    lastName: '',
    jobTitle: '',
    companyName: '',
    phone: '',
    email: '',
    message: '',
  });

  // encodes the captured form data in the format that Netlify's backend requires
  // example: form-name=contact&firstName=a&lastName=b&jobTitle=a&companyName=a&phone=3&email=me%40you.com&message=tes
  const encode = (data) => {
    return Object.keys(data)
      .map(
        (key) => encodeURIComponent(key) + '=' + encodeURIComponent(data[key])
      )
      .join('&');
  };

  const handleChange = (event) => {
    setFormState({
      ...formState,
      [event.target.name]: event.target.value,
    });
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    const form = event.target;
    fetch('/', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: encode({
        'form-name': form.getAttribute('name'),
        ...formState,
      }),
    })
      .then(() => navigate(form.getAttribute('action')))
      .catch((error) => alert(error));
  };

  return (
    <>
      <SEO title="Contact" />
      <StyledContactPage className="page">
        <article>
          <h3>get in touch</h3>
          <p>
            For a more indepth look at our protection services and rates call us
            at 1-800-Get-Safe or fill out the form below! A representative will
            be in touch shortly.
          </p>
          <form
            name="contact"
            method="POST"
            data-netlify="true"
            data-netlify-honeypot="bot-field"
            action="/thank-you"
            onSubmit={handleSubmit}
          >
            <input type="hidden" name="form-name" value="contact" />
            <div className="form-group">
              <label htmlFor="first-name" className="sr-only">
                First Name
              </label>
              <input
                id="first-name"
                name="firstName"
                type="text"
                placeholder="First Name"
                className="form-control"
                required
                onChange={handleChange}
                value={formState.firstName}
              />
              <label htmlFor="last-name" className="sr-only">
                Last Name
              </label>
              <input
                id="last-name"
                name="lastName"
                type="text"
                placeholder="Last Name"
                className="form-control"
                required
                onChange={handleChange}
                value={formState.lastName}
              />
              <label htmlFor="job-title" className="sr-only">
                Job Title
              </label>
              <input
                id="job-title"
                name="jobTitle"
                type="text"
                placeholder="Job Title"
                className="form-control"
                required
                onChange={handleChange}
                value={formState.jobTitle}
              />
              <label htmlFor="company-name" className="sr-only">
                Company Name
              </label>
              <input
                id="company-name"
                name="companyName"
                type="text"
                placeholder="Company Name"
                className="form-control"
                required
                onChange={handleChange}
                value={formState.companyName}
              />
              <label htmlFor="phone" className="sr-only">
                Phone
              </label>
              <input
                id="phone"
                name="phone"
                type="number"
                placeholder="Phone Number"
                className="form-control"
                required
                onChange={handleChange}
                value={formState.phone}
              />
              <label htmlFor="email" className="sr-only">
                Phone
              </label>
              <input
                name="email"
                type="email"
                placeholder="email"
                className="form-control"
                onChange={handleChange}
                value={formState.email}
              />
              <label htmlFor="message" className="sr-only">
                How can we help you?
              </label>
              <textarea
                id="message"
                name="message"
                rows="5"
                placeholder="message"
                className="form-control"
                required
                onChange={handleChange}
                value={formState.message}
              ></textarea>
            </div>
            <button type="submit" className="submit-btn btn">
              submit here
            </button>
          </form>
        </article>
      </StyledContactPage>
      {/* </div> */}
      {/* /.page */}
    </>
  );
};

export default ContactPage;