2

I have a basic Netlify form (based on this guide) with name, email and message fields. With the following submit function:

const handleSubmit = event => {
    event.preventDefault();
    const data = {};
    const scopedForm = [...formState];

    let isValidForm = validateForm(scopedForm);
    setFormState([...scopedForm]);

    if (!isValidForm) return false;

    formInputs.forEach(input => data[input.name] = input.value);

    fetch(`/`, {
      method: `POST`,
      headers: {
        'Accept': `application/x-www-form-urlencoded;charset=UTF-8`,
        'Content-Type': `application/x-www-form-urlencoded`,
      },
      body: encode({
        'form-name': `Contact Form`,
        ...data,
      }),
    })
      .then(() => console.log(`OK`))
      .catch(error => alert(error));
  };

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

Pretty simple, besides the validations, I create a data object and I fill it with a pair of data[input.name] = input.value. Everything works as expected locally, as well as in develop and build mode. I can see a POST request, however, in production, it turns into a GET:

Fetch request in production

I've tried changing the built-in fetch to axios but the result is the same. I don't know if I need to add some custom configuration in my server or how to bypass this.

My resulting HTML structure is:

<form name="Contact Form" method="POST" action="/" data-netlify="true" data-netlify-honeypot="bot-field" data-netlify-recaptcha="true">
   <div><label for="form-name"><input type="hidden" name="form-name" value="Contact Form"></label></div>
   <div><label for="bot-field"><input type="hidden" name="bot-field" value=""></label></div>
   <div><label for="name">Name:<input type="text" name="name" value="Chancellor Lawson"></label></div>
   <div><label for="email">Email:<input type="text" name="email" value="fivyhohy@mailinator.com"></label></div>
   <div><label for="message">Message:<textarea name="message">Ea quisquam ea vel e</textarea></label></div>
   <button type="submit">Send</button>
</form>

I have read a lot of similar issues, articles, and guides but none helped.

Ferran Buireu
  • 28,630
  • 6
  • 39
  • 67
  • Could`validForm` be returning `False` before fetching? – Alex Douglas Jul 24 '20 at 17:24
  • No, because the `console` is prompting the `OK` message. I've tried removing the condition and the result is the same. – Ferran Buireu Jul 24 '20 at 17:36
  • 1
    It's unlikely to be related to your actual problem, but telling the server that you'll only accept a **responses** that is `application/x-www-form-urlencoded;charset=UTF-8` doesn't make sense. – Quentin Jul 24 '20 at 17:49
  • 1
    Check the *Type* column on the Network tab in Chrome. Make sure that the request you are looking at is one triggered by xhr. If it isn't, the code you provided isn't what is generating the HTTP request. – Quentin Jul 24 '20 at 17:50
  • That did the trick @Quentin. Once I removed the `Accept` header it worked. If you add an answer I'll accept to close the issue. – Ferran Buireu Jul 24 '20 at 18:00

1 Answers1

0

In order to close the issue, I will answer my own question, giving all the merits to Quentin. As he pointed out, the solution was removing the Accept header since it only was accepting application/x-www-form-urlencoded;charset=UTF-8 requests. So the header should look like:

  headers: {
    'Content-Type': `application/x-www-form-urlencoded`,
  },

From MDN documentation:

The Accept request HTTP header advertises which content types, expressed as MIME types, the client is able to understand. Using content negotiation, the server then selects one of the proposals, uses it and informs the client of its choice with the Content-Type response header. Browsers set adequate values for this header depending on the context where the request is done: when fetching a CSS stylesheet a different value is set for the request than when fetching an image, video, or script.

Ferran Buireu
  • 28,630
  • 6
  • 39
  • 67