React Form submission leads to 303 followed by 404

Hi There,

I’m a newbie with Netlify, as well as with React, I’ve been trying to deploy an app with 2 forms one in the contact page and the other in the store page, I’ve managed to deploy it previously in one link https://naughty-neumann-838e54.netlify.app and both forms are working fine there, however, I was trying to add a new field in the store for a delivery address and for some reason no matter how much updated the index.html file it just wouldn’t receive the address field in the form submissions, for this reason I attempted to alter the code a few times and deploy it in a new site, https://ululatus.netlify.app taking the code was changed a bit, I started receiving a 303 post followed by a 404 on each form submission, the forms are created on the netlify > forms page, but no submissions arrive.

I went and checked the forum for solutions as well as the guides provided, and attempted to change my html file to include just netlify, then data-netlify=“true”, data-netlify=true, netlify-honeypot=“bot-field”, data-netlify-recaptcha=“true” and some permutations of this, I have also attempted to include these parameters in the jsx of each component, attempted to change the post request path, even tried to include another hidden form in the jsx, attempted the hidden input field with the form-name as it seemed like the decription of my problem.

Unfortunately I didn’t succeed in any way. I have thought that it may be happening due to already having the same 2 forms deployed on the first site, but it doesn’t make much sense to me as even the recaptcha keys are different.

Here follows the code from the index.html file and both components related to the forms (apologies for the bits of portuguese and unrelated comments in the code):

index.html
<meta charset="utf-8">

<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">

<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

<meta name="theme-color" content="#000000">

<!--

  manifest.json provides metadata used when your web app is added to the

  homescreen on Android. See https://developers.google.com/web/fundamentals/web-app-manifest/

-->

<link rel="manifest" href="%PUBLIC_URL%/manifest.json">

<!--

  Notice the use of %PUBLIC_URL% in the tags above.

  It will be replaced with the URL of the `public` folder during the build.

  Only files inside the `public` folder can be referenced from the HTML.

  Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will

  work correctly both with client-side routing and a non-root public URL.

  Learn how to configure a non-root public URL by running `npm run build`.

-->

<!--Materialize-->

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">

<!--Materialize Icons-->

<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

<title>React App</title>
<form name="contactos" netlify netlify-honeypot="bot-field" data-netlify-recaptcha="true" hidden>

  <input type="text" name="name" />

  <input type="email" name="email" />

  <textarea name="message"></textarea>

</form>

<form name="loja" netlify netlify-honeypot="bot-field" data-netlify-recaptcha="true" hidden>

  <input type="text" name="name" />

  <input type="email" name="email" />

  <input type="text" name="address" />

  <input type="text" name="message" hidden/>

  <input type="text" name="total" hidden/>

</form>



<noscript>

  You need to enable JavaScript to run this app.

</noscript>

<div id="root"></div>

<!--

  This HTML file is a template.

  If you open it directly in the browser, you will see an empty page.

  You can add webfonts, meta tags, or analytics to this file.

  The build step will place the bundled scripts into the <body> tag.

  To begin the development, run `npm start` or `yarn start`.

  To create a production bundle, use `npm run build` or `yarn build`.

-->

<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
Contactos.js

import React, { Component } from ‘react’;

import { connect } from ‘react-redux’

import { GoInfo } from “react-icons/go”;

import {IoIosContact} from “react-icons/io”;

import {MdEmail} from “react-icons/md”;

import ReCAPTCHA from “react-google-recaptcha”;

const encode = (data) => {

return Object.keys(data)

    .map(key => encodeURIComponent(key) + "=" + encodeURIComponent(data[key]))

    .join("&");

}

const recaptchaRef = React.createRef();

class Contactos extends Component {

constructor(props) {

    super(props);

    this.state = { name: "", email: "", message: "" };

  }

  

handleSubmit = e => {

    

    fetch("/", {

      method: "POST",

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

      onSubmit: () => { recaptchaRef.current.execute(); },

      body: encode({ "form-name": "contactos", ...this.state })

    })

      .then(() => window.M.toast({ html: 'Mensagem Enviada', classes: 'toastposition green' }) )

      .catch(error => window.M.toast({ html: 'Ocorreu um erro', classes: 'toastposition red' }));



    e.preventDefault();

    this.setState({

        

      name: '',

      email: '',

      message: ''

                

    });

  };



  handleChange = e => this.setState({ [e.target.name]: e.target.value });

  onChange(value) {

    console.log("Captcha value:", value);

  }

 

render() {

    const { name, email, message } = this.state;

    return (

        

        <div className="container">

            <h3 className="center">Contactos</h3>

            <div className="box">

            <div className="contact-box">

            <div>

            <form className="contact-form" onSubmit={this.handleSubmit}>

            

            <input type="hidden" name="form-name" value="contactos" />

    

                <label className="fields"><i><IoIosContact size={30}/></i>Inserir nome:</label>

                <input type="text" name="name" value={name} onChange={this.handleChange}/><br></br><br></br>

                <label className="fields"><i><MdEmail size={30}/></i>Inserir email:</label>

                <input type="email" name="email" value={email} onChange={this.handleChange}/>

                <label>Inserir mensagem:

                <textarea name="message" value={message} onChange={this.handleChange} /></label>

                

               <ReCAPTCHA

                  ref={recaptchaRef}

                  sitekey="6Lf4x-sUAAAAAA6cNCiqvQfyGYt9IRZaoCjrDeSe"

                  onChange={this.onChange}

                  theme="light"

                  size="invisible"                      

                  className="captcha"

                  

                /> 

                <p><input className="send-button" type="submit" value="Enviar" /></p>

            

            </form>

            </div>

            <div className="contact-info">

                <i className="info-icon"><GoInfo size={140}/></i>

                <br></br>

                    <b>ululatus edições, C.R.L.</b><br></br>

                    Rua Cristóvão Colombo, n°12, 4°F<br></br>

                    2675-593 Odivelas<br></br>

                    Portugal<br></br><br></br>

                    <b>Telefone:</b><br></br> 21XXXXXX<br></br>

                    <b>E-mail:</b><br></br> ululatus.edicoes@gmail.com<br></br><br></br>

                    <b>Administração:</b><br></br>

                    Patrick Rocha<br></br><br></br>

                    <b>Coordenação Editorial:</b><br></br>

                    Samuel Costa Velho

            </div>

            </div>

           </div>

       </div>

       

   )

           

   }}

export default connect()(Contactos)

Recipe.js

import React, { Component } from ‘react’

import { connect } from ‘react-redux’

import {IoIosContact} from “react-icons/io”;

import {MdEmail, MdLocationOn} from “react-icons/md”;

import ReCAPTCHA from “react-google-recaptcha”;

const encode = (data) => {

return Object.keys(data)

    .map(key => encodeURIComponent(key) + "=" + encodeURIComponent(data[key]))

    .join("&");

}

const recaptchaRef = React.createRef();

//import { addShipping } from ‘./actions/cartActions’

class Recipe extends Component{

constructor(props) {

    super(props);

    function replacer(key, value) {

        if (key=="img") return undefined;

        else if (key=="link") return undefined;

        else if (key=="desc") return undefined;

        else if (key=="id") return undefined;

        else return value;

    }

    // let itemsObj = JSON.stringify(this.props.addedItems)

    const itemsObj = JSON.stringify(this.props.addedItems, replacer)

    this.state = { name: "", email: "", address: "", message: itemsObj, total: `€${this.props.total}` };

  }

  

  handleSubmit = e => {

    fetch("/", {

      method: "POST",

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

      onSubmit: () => { recaptchaRef.current.execute(); },

      body: encode({ "form-name": "loja", ...this.state })

    })

      .then(() => window.M.toast({ html: "Encomenda Enviada <br> Entraremos em contacto em breve", classes: 'toastposition green' }))

      .catch(error => window.M.toast({ html: 'Ocorreu um erro', classes: 'toastposition red' }));



    e.preventDefault();

    

    this.setState({

        

        name: '',

        email: '',

        address: '',

        message: '',

        total: ''

        

      });

  };



  handleChange = e => this.setState({ [e.target.name]: e.target.value });

/* componentWillUnmount() {

     if(this.refs.shipping.checked)

          this.props.substractShipping()

}

handleChecked = (e)=>{

    if(e.target.checked){

        this.props.addShipping();

    }

    else{

        this.props.substractShipping();

    }

} */

onChange(value) {

    console.log("Captcha value:", value);

  }

render(){

      

    const { name, email, address, message, total } = this.state;

    return(

        <div className="container">



            <div className="collection">

                

                {/* <li className="collection-item">

                        <label>

                            <input type="checkbox" ref="shipping" onChange= {this.handleChecked} />

                            <span>Shipping(+6$)</span>

                        </label>

                    </li> */}

                    <li className="collection-item"><b>Total: €{this.props.total} </b></li>

                </div>

                <div className="checkout">

                <div>

                <form className="contact-store" onSubmit={this.handleSubmit}>

                

                <input type="hidden" name="form-name" value="loja" />

                    

                    <label className="fields"><i><IoIosContact size={30}/></i>Inserir nome:</label>

                    <input type="text" name="name" value={name} onChange={this.handleChange}/><br></br><br></br>

                    <label className="fields"><i><MdEmail size={30}/></i>Inserir email:</label>

                    <input type="email" name="email" value={email} onChange={this.handleChange}/><br></br><br></br>

                    <label className="fields"><i><MdLocationOn size={30}/></i>Inserir morada de entrega (Incluir código postal):</label>

                    <input type="text" name="address" value={address} onChange={this.handleChange}/><br></br><br></br>

                    <input type="text" name="message" value={message} onChange={this.handleChange} hidden/>

                    <input type="text" name="total" value={total} onChange={this.handleChange} hidden/><br></br><br></br>

                    

                    <ReCAPTCHA

                    ref={recaptchaRef}

                    sitekey="6Lf4x-sUAAAAAA6cNCiqvQfyGYt9IRZaoCjrDeSe"

                    onChange={this.onChange}

                    size="invisible"

                    theme="light"

                    

                    /> 

                

                    <button type="submit" className="waves-effect waves-light btn checkout-btn">Efectuar Encomenda</button>

                </form>

                </div>

                    

                </div>

             </div>

    )

}

}

const mapStateToProps = (state)=>{

return{

    addedItems: state.addedItems,

    total: state.total

}

}

const mapDispatchToProps = (dispatch)=>{

return{

    addShipping: ()=>{dispatch({type: 'ADD_SHIPPING'})},

    substractShipping: ()=>{dispatch({type: 'SUB_SHIPPING'})}

}

}

export default connect(mapStateToProps,mapDispatchToProps)(Recipe)

hi there, welcome.

did you give this a read through already?

I’m not convinced we can support multiple forms on one page.

1 Like

Hi perry,

the thing is that they work in the first link mentioned in my post https://naughty-neumann-838e54.netlify.app

I just changed the code enough times so that when I redeployed to a different instance something was messed in the code and now it doesn’t work.

The first link is still working I didn’t deploy again so I could at least download the build folder to compare but for now wasn’t successful in trying to adapt the index.html the same way as in the deploy.

Thanks for the help

1 Like

Ok so I think I found a solution, even thought not optimal, I went and copied all the files I had an remove all entries from recaptcha leaving just the honeypot stuff, and it apparently works, I think my recaptcha logic must be faulty, if someone has some tips on that would be nice. For now I just redeployed it in another instance an it works with honeypot.

2 Likes