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)