React form POST to Express server not working - REST - reactjs

I am trying to POST a HTML form to an Express server.
When I use a REST client, the POST request works fine and data is correctly sent and registered in DB. So server-side looks good. But my React code won't POST anything. There is no error in the console and input values are correctly targetted. I've tried native fetch method and also Axios, but both are not working. I hope someone will help me on that as I'm not very familiar with REST api's yet.
Here is my Form component :
import React, { useState } from "react";
import Header from "./Header";
import Footer from "./Footer";
const Form = () => {
{/* POST REQUEST */}
const handleFormSubmit = (event) => {
const name = event.target.elements.name.value;
const description = event.target.elements.description.value;
const email = event.target.elements.email.value;
const number = event.target.elements.number.value;
const website = event.target.elements.website.value;
const social_media1 = event.target.elements.social_media1.value;
fetch("http://192.168.1.101:7777/form", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
name: name,
description: description,
email: email,
number: number,
website: website,
social_media1: social_media1,
}),
})
.then((response) => {
console.log(response);
return response.json();
})
.catch((error) => console.log(error));
};
return (
<>
{/* SOME PAGE STUFF */}
<Header />
<div className="formTitle">
<h3>Create your artist page</h3>
<p>Some fields are required</p>
</div>
{/* HTML FORM */}
<form onSubmit={handleFormSubmit} className="form">
<div>
<legend>About you</legend>
{/* NAME */}
<label htmlFor="name">
Artist name <span className="required">required</span>
</label>
<input
type="text"
id="name"
name="name"
required
placeholder="Oasis"
/>
</div>
<div>
{/* DESCRIPTION */}
<label htmlFor="description">
Description <span className="required">required</span>
</label>
<textarea
rows="5"
type="text"
id="description"
name="description"
required
placeholder="Insert a short description here"
></textarea>
</div>
<div>
<legend>Contact</legend>
{/* EMAIL */}
<label htmlFor="email">
Email address <span className="required">required</span>
</label>
<input
type="email"
id="email"
name="email"
required
placeholder="contact#oasis.uk"
/>
{/* NUMBER */}
<label htmlFor="number">Phone number </label>
<input
type="text"
id="number"
name="number"
required
placeholder="+34 6 12 34 56 78"
/>
{/* WEBSITE */}
<label htmlFor="website">Website </label>
<input
type="text"
id="website"
name="website"
required
placeholder="https://oasis.com"
/>
</div>
<div>
<legend>Social media</legend>
{/* SOCIAL LINK 1 */}
<label htmlFor="social_media1">
Social media link 1 <span className="required">required</span>
</label>
<input
type="text"
id="social_media1"
name="social_media1"
required
placeholder="https://instagram.com/oasis"
/>
</div>
<button className="submit" type="submit">
Submit
</button>
</form>
<div className="temp"></div>
<Footer />
</>
);
};
export default Form;

You can try this method:
const form_Data = new FormData(event.target);
const finalData = {};
for (let [key, value] of form_Data.entries()) {
finalData[key] = value;
}
console.log(finaldata);
fetch("http://192.168.1.101:7777/form", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: finaldata
})
.then((response) => {
console.log(response);
return response.json({response);
})
.catch((error) => console.log(error));
};
First, you should convert all form data into new FormData and you can pass this object to you fetch's POST method
I think it should be work.

Related

ReactJS: Redirect after form submit without refresh

i have created a form which calls the search function after pressing submit button. I want the results of the search to be displayed in another function component (have used React Context for this purpose).
However, i faced an issue where i cannot link it to another route /yourstage/results WITHOUT refreshing the page. If the page is refreshed, my seachResult stored in state will be gone.
import React, { Fragment, useState, useEffect, useContext } from "react";
import { withRouter, Link } from "react-router-dom";
import searchResultContext from "./SearchResultContext";
const Search = () => {
const [wave, setWave] = useState("$perc");
const [pack_hu, setPackHu] = useState("$perc");
const { searchResult, setSearchResult } = useContext(searchResultContext);
useEffect(() => {
console.log(JSON.stringify(searchResult));
}, [searchResult]);
//submit a form to search
const submitSearch = async (e) => {
e.preventDefault()
try {
const response = await fetch(
`http://localhost:5000/yourstage/search/${wave}/${pack_hu}`,
{
method: "GET",
headers: { "Content-Type": "application/json" },
}
);
setSearchResult(await response.json());
//Reset Form and State
document.getElementById("searchForm").reset();
setWave("$perc");
setPackHu("$perc");
} catch (error) {
console.error(error.message);
}
};
//return the form html
return (
<Fragment>
<h1 className="text-center mt-3">Search</h1>
<form id="searchForm" onSubmit={submitSearch}>
<div className="form-group row">
<label htmlFor="Wave" className="col-sm-2 col-form-label">
Wave:
</label>
<div className="col-sm-10">
<input
type="text"
className="form-control"
placeholder="Wave Number"
maxLength="10"
onChange={(e) => setWave(e.target.value)}
/>
</div>
</div>
<div className="form-group row">
<label htmlFor="pack_hu" className="col-sm-2 col-form-label">
Pack HU:
</label>
<div className="col-sm-10">
<input
type="text"
className="form-control"
placeholder="Pack HU"
maxLength="10"
onChange={(e) => setPackHu(e.target.value)}
/>
</div>
</div>
<div className="row text-center mt-5">
{/**Search based on parameter*/}
<div className="col-6">
<button type="submit" className="btn-lg btn-primary">
<Link to="/yourstage/results">Search</Link>
</button>
</div>
</div>
</form>
</Fragment>
);
};
export default withRouter(Search);

Netify-gatsby form submission not working with custom Success Component

I am using Netify-form with gatsby JS. I am trying to show a success alert Component when a user submits the form. This is working fine, but I am not able to get form data under my Netify account.
handleSubmit = (e) => {
this.setState({showSuccessMsg: true});
e.preventDefault();
};
<form name="subscribe"
method="POST"
onSubmit={this.handleSubmit} // custom handler
action=""
data-netlify="true"
data-netlify-honeypot="bot-field"
className="form-inline d-flex">
<input type="hidden" name="form-name" value="subscribe"/>
<input type="hidden" name="bot-field"/>
.....
.....
<button type="submit" className="btn btn-primary mx-auto">
Subscribe
</button>
</form>
<div>
{this.state.showSuccessMsg ? <SuccessAlert/> : ''}
</div>
PS: commenting this // onSubmit={this.handleSubmit}, I am able to get data but I am loosing showing success alert.
Netlify forms setup - Success messages
By default, when visitors complete a form, they will see a generically styled success message with a link back to the form page. You can replace the default success message with a custom page you create by adding an action attribute to the tag, entering the path of your custom page (like "/pages/success") as the value. The path must be relative to the site root, starting with a /.
Or you could check out this guide from Netlify - How to Integrate Netlify’s Form Handling in a React App which has a gatsby specific example for submitting with js.
import React, {useState} from 'react'
function encode(data) {
return Object.keys(data)
.map((key) => encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))
.join('&')
}
export default function Contact() {
const [state, setState] = useState({})
const handleChange = (e) => {
setState({ ...state, [e.target.name]: e.target.value })
}
const handleSubmit = (e) => {
e.preventDefault()
const form = e.target
fetch('/', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: encode({
'form-name': form.getAttribute('name'),
...state,
}),
})
.then(() => alert('success')))
.catch((error) => alert(error))
}
return (
<>
<h1>Contact</h1>
<form
name="contact"
method="post"
action="/thanks/"
data-netlify="true"
data-netlify-honeypot="bot-field"
onSubmit={handleSubmit}
>
{/* The `form-name` hidden field is required to support form submissions without JavaScript */}
<input type="hidden" name="form-name" value="contact" />
<div hidden>
<label>
Don’t fill this out: <input name="bot-field" onChange={handleChange} />
</label>
</div>
<label>
Your name:
<input type="text" name="name" onChange={handleChange} />
</label>
<label>
Your email:
<input type="email" name="email" onChange={handleChange} />
</label>
<label>
Message:
<textarea name="message" onChange={handleChange} />
</label>
<button type="submit">Send</button>
</form>
</>
)
}

Laravel React MySQL Routing Issue

I am trying to make it so that I can register a user but I am getting a 404 error, assuming that means that react is unable to find the route established by the api.php file, is there anything else that I am missing? I have already set it in the package.json file that the proxy is set to "localhost:8000" (the port I chose to use for laravel's backend stuff). I am confused on why it's not hitting this route upon submitting. I feel like I'm close but I am new to using php as the backend so any insight would be helpful.
I am also creating something where the user is able to play music on the app, so there is a route for that labeled "shop", and that does not work for the sole reason that I have not set that route up (also gives a 404 error).
Below are my api routes that I am trying to get react to detect
<?php
Route::post('register','UserController#register');
Route::post('login','UserController#login');
Route::post('profile','UserController#getAuthenticatedUser');
Route::middleware('auth:api')->get('/user', function(Request $request){
return $request->user();
});
?>
And this is the React portion of my registration file.
import React, { Component } from 'react';
import { register } from './UserFunctions';
class Register extends Component {
constructor() {
super()
this.state = {
first_name: '',
last_name: '',
email: '',
password: '',
errors: {},
}
this.onChange = this.onChange.bind(this)
this.onSubmit = this.onSubmit.bind(this)
}
onChange(e) {
this.setState({ [e.target.name]: e.target.value })
}
onSubmit(e) {
e.preventDefault()
const newUser = {
name: this.state.first_name + ' ' + this.state.last_name,
email: this.state.email,
password: this.state.password
}
register(newUser).then(res => {
if (res) {
this.props.history.push('/login')
}
})
}
render() {
return (
<div className="container">
<div className="row">
<div className="col-md-6 mt-5 mx auto">
<form noValidate onSubmit={this.onSubmit}>
<h1 className="h3 mb-3 font-wieght-normal">
Register
</h1>
<div className="form-group">
<label htmlFor="first_name">First Name</label>
<input type="text" className="form-control" name="first_name" placeholder="Enter First Name" value={this.state.first_name} onChange={this.onChange} />
<label htmlFor="last_name">Last Name</label>
<input type="text" className="form-control" name="last_name" placeholder="Enter Last Name" value={this.state.last_name} onChange={this.onChange} />
<label htmlFor="email">Email Address</label><br />
<input type="email" className="form-control" name="email" placeholder="Enter Email" value={this.state.email} onChange={this.onChange} />
<br />
<label htmlFor="password">Desired Password</label><br />
<input type="password" className="form-control" name="password" placeholder="Enter Password" value={this.state.password} onChange={this.onChange} />
</div>
<button type="submit" className="btn btn-lg btn-primary btn-block">Register</button>
</form>
</div>
</div>
</div>
)
}
}
export default Register
I have those post routes defined, but when I press submit within my register form, I get a 404 error saying that it can't find this route.
Can you show me your
import { register } from './UserFunctions';
file so that I can see the url path defined.
Assuming this route is inside your routes/api.php
Route::group(['middleware' => 'api', 'prefix' => 'v1'], function(){
Route::post('register', 'RegisterController#index');
});
and in JS file
import axios from 'axios'
export const register = newUser => {
return axios
.post('api/v1/register', newUser,
{
headers: { 'Content-Type': 'application/json' }
})
.then(res => {
console.log(res)
})
.catch(err => {
console.log(err)
})
}

Submitted react stateful form with Netlify always return 404

I've created a form using React and Bulma. Now I wanted to incorporate Netlify and just use their form handling. I've included 'data-netlify'='true' and 'data-netlify-honeypot'='bot-field' and used their suggested way of incorporating the fetch request onSubmit. But I always return a 404 on submit and I don't know why. Any help would be greatly appreciated.
I've tried all the steps that Netlify has suggested. At least I think I have.
import React, { Component } from 'react';
import 'bulma/css/bulma.css';
import '../css/ContactFormAndFooter.css';
import Fade from 'react-reveal/Fade';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import { faUser, faEnvelope, faPhone } from '#fortawesome/free-solid-svg-icons';
const encode = (data) => {
return Object.keys(data)
.map(key => encodeURIComponent(key) + "=" + encodeURIComponent(data[key]))
.join("&");
}
class ContactInfoForm extends Component {
constructor(props) {
super(props)
this.state = {
'name': '',
'email': '',
'phone': '',
'details': ''
}
}
handleInputChange = e => this.setState({ [e.target.name]: e.target.value })
handleSubmit = (e) => {
fetch('/', {
method: 'POST',
headers: { 'Content-Type': "application/x-www-form-urlencoded" },
body: encode({ "form-name": "contact", ...this.state })
})
.then(() => {
this.setState({
name: '',
email: '',
phone: '',
details: ''
});
alert('Success!');
})
.catch(error => alert(error));
e.preventDefault();
}
render() {
const { name, email, phone, details } = this.state;
return (
<section className='section contact-section'>
<Fade left>
<h3 className='title is-3'>Please introduce yourself and tell me a little bit about your project</h3>
</Fade>
<Fade right>
<div className='container is-centered card box contact-container'>
<form
name='contact'
method='POST'
onSubmit={this.handleSubmit}
data-netlify-honeypot='bot-field'
data-netlify='true'
>
<input type="hidden" name="form-name" value="contact" />
<p className="hidden">
<label>Don’t fill this out if you're human: <input name="bot-field" /></label>
</p>
<div className='field'>
<div className='control has-icons-left'>
<input
className='input has-text-weight-light'
name='name'
type='text'
value={name}
onChange={this.handleInputChange}
placeholder='First and Last Name'
/>
<span className='icon is-small is-left'>
<FontAwesomeIcon icon={faUser} style={{'color':'#4B0082'}} />
</span>
</div>
</div>
<div className='field'>
<div className='control has-icons-left'>
<input
className='input has-text-weight-light'
name='email'
type='email'
value={email}
onChange={this.handleInputChange}
placeholder='Email'
/>
<span className='icon is-small is-left'>
<FontAwesomeIcon icon={faEnvelope} style={{'color':'#4B0082'}} />
</span>
</div>
</div>
<div className='field'>
<div className='control has-icons-left'>
<input
className='input has-text-weight-light'
name='phone'
type='number'
value={phone}
onChange={this.handleInputChange}
placeholder='Phone Number'
/>
<span className='icon is-small is-left'>
<FontAwesomeIcon icon={faPhone} style={{'color':'#4B0082'}} />
</span>
</div>
</div>
<div className='field'>
<label className='label has-text-grey-light has-text-weight-light'>Project Description</label>
<div className='control'>
<textarea
className='textarea'
name='details'
value={details}
onChange={this.handleInputChange}
/>
</div>
</div>
<div className="control has-text-centered">
<button className='button has-text-white' type='submit'>Submit</button>
</div>
</form>
</div>
</Fade>
</section>
)
}
}
export default ContactInfoForm;
The 404 almost certainly occurs because the form has not been detected by Netlify. Netlify returns an HTTP 404 status for ALL HTTP(s) POST operations EXCEPT ones that are either proxy'd to another site or function (then we proxy the POST) OR requests that match a URL we are expecting a POST to - one we've been notified at deploy time will be the endpoint for form submissions.
How to notify Netlify that an endpoint is intended for form submissions? This situation usually happens because you have no plain-html form definition or it doesn't include the netlify or data-netlify=true form parameter in the html <form ...> definition, which is what we parse to discover the endpoint. We don't parse javascript, only html. Some frameworks (I thought React was one, but your usage may not lead to this) will create html files from your JS and deploy those and we'll parse those. You might want to download a copy of your deploy to confirm that there is a plain-html version of your form with the endpoint you are trying to post to (action= parameter) specified. The below screenshot shows the icon to download a copy of your deploy from any successful deploy's logs page:

Reactjs post multiple values including a file to ASP.Net Core controller action

I need to post string and file from ReactJS to ASP.Net Core 2.0 controller method and bump into 500 error and the request never hits the controller action method. Here is the ReactJS code:
private submit(e) {
e.preventDefault();
let data = new FormData();
let str = (document.getElementById('TweetString') as HTMLInputElement).value;
let file = (document.getElementById('TweetFile') as HTMLInputElement).files[0];
data.append("TweetString", str);
data.append("File", file);
fetch('/home/post', {
method: "post",
headers: { 'Content-Type': 'multipart/form-data' },
body: data
}).then(function (res) {
if (res.ok) {
console.log("Perfect! ");
} else
console.error("Post error: "+ res.status);
}).catch(e => {
console.log("error: " + e);
});
}
<form id="frmTweet" encType="multipart/form-data">
<div className="row">
<div className="col-md-6">
<input type="text" className="form-control" id="TweetString" placeholder="TweetString"></input>
</div>
<div className="col-md-6">
<input type="file" className="form-control" id="TweetFile" placeholder="Select file to upload..."></input>
</div>
</div>
<div className="row">
<button onClick={this.submit.bind(this)} className="button">Submit</button>
</div>
</form>
Here is my controller method signature:
[HttpPost]
public async Task<IActionResult> Post([FromForm]string TweetString, [FromForm]IFormFile File) {}
Any advice and insight is appreciated. Thanks.
Thanks for your post, this worked for me and I'd like to share an example for future reference.
To use axios with react you'll need the following npm packages: react, axios, prop-types, react-axios
I've got this React code on client side:
import React, { Component } from 'react';
import { post } from 'axios';
export class FileUpload extends Component {
static displayName = FileUpload.name;
async handleSubmit(e) {
e.preventDefault();
const url = 'api/Books';
const formData = new FormData();
formData.append('file', this.refs.File.files[0]);
var book = {
title: this.refs.Title.value,
author: this.refs.Author.value,
language: this.refs.Language.value
};
formData.append('metadata', JSON.stringify(book));
post(url, formData);
}
render() {
return (
<div>
<h1>File Upload</h1>
<form onSubmit={e => this.handleSubmit(e)}>
<div className="form-group">
<label>Title</label>
<input className="form-control" ref="Title" required />
</div>
<div className="form-group">
<label>Author</label>
<input className="form-control" ref="Author" required />
</div>
<div className="form-group">
<label>Language</label>
<select className="form-control" ref="Language">
<option>English</option>
<option>German</option>
<option>French</option>
</select>
</div>
<div className="form-group">
<label>File</label>
<input type="file" className="form-control-file" ref="File" required />
</div>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
</div>
);
}
}
and the following C# code in the .NET Core Web API 2 backend:
[HttpPost]
public void PostBook(IFormCollection bookData)
{
var book = JsonConvert.DeserializeObject<Book>(bookData["metadata"]);
_bookService.AddBookToDb(book, bookData.Files[0]);
}
Solution:
Client: use axios
Server: Use IFormCollection

Resources