Trouble with React Form POST request - reactjs

I am having difficulty understanding what I'm doing wrong on this POST request. The POST request itself is working which I confirmed in the network tab.
However, I am only able to post static values that I define, rather than the values from the form fields. Please have a look. This is driving me up the wall. Thank you!
Notes:
In TestForm.js it doesn't actually seem to console.log the response as I'm asking it to.
I receive no errors.
This does POST to my server, and into Postgres, and I will show below what that looks like when I console.log.
console.log(sauces) at the start of HandleSubmit does in fact show "sauces" currectly, which is whatever is input into the first form field.
GitHub Repository
The React Form Component (TestForm.js):
function TestForm() {
const [sauce, setSauce] = useState('');
const [presentation, setPresentation] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
fetch('http://jyh:3000', {
method: 'POST',
headers: {'Content-Type':'application/json'},
body: JSON.stringify({
"test_name": sauce,
"test_sauce": presentation,
}),
}).then((res) => {
console.log(res.json());
return res.json();
}).catch((err) => {
console.log(err.message);
});
};
return (
<form onSubmit={handleSubmit}>
<div className="color-section" id="reviewASauce">
<div className="container-fluid">
<h2>Review a Sauce</h2><br />
Trying a sauce that is already in our database? Review it!
<br />
<br />
<br />
<h2>Sauce Name</h2>
<Form.Label htmlFor="test_name">
</Form.Label>
<Form.Control
type="text"
id="test_name"
aria-describedby="test_name"
placeholder="Input the name of the sauce here."
value={sauce}
onChange={(e) => setSauce(e.target.value)}
/>
<Form.Text id="test_name" muted>
</Form.Text>
<br />
<br />
<Form.Label htmlFor="test_sauce">
</Form.Label>
<Form.Control
type="text"
id="test_sauce"
aria-describedby="test_sauce"
placeholder="Input the name of the sauce here."
value={presentation}
onChange={(e) => setPresentation(e.target.value)}
/>
<Form.Text id="test_sauce" muted>
</Form.Text>
<br />
<br />
<Button variant="dark" type="submit">
Submit
</Button>
</div>
</div>
</form>
);
}
export default TestForm;
Server index.js:
app.post('/', async (req, res) => {
await TestTable.create({
test_name: "test_name",
test_sauce: "test_sauce",
}).then((data) => {
console.log(data.toJSON());
}).catch((err) => {
console.log(err);
});
});
What the terminal displays when clicking submit:
{
id: 100,
test_name: 'test_name',
test_sauce: 'test_sauce',
updatedAt: 2022-12-21T02:54:42.447Z,
createdAt: 2022-12-21T02:54:42.447Z
}
I have tried to change and arrange both the HandleSubmit function as well as my app.post, but no matter what I do I cannot seem to get the form data from TestForm.js to index.js.

In your Server index.js you are not using the params you sent from the frontend.
It looks you are using express for you server.
Try doing something like
await TestTable.create({
test_name: req.body.test_name,
test_sauce: req.body.test_sauce
})
Check this: How to access the request body when POSTing using Node.js and Express?

Related

POST request in react hook form not fetching the user input

I am working on an address book and I have fetched all the data from this API url:
https://jsonplaceholder.typicode.com/users
The API cannot really be modified, but it should behave "like if" according to this message in the documentation: "resource will not be really updated on the server but it will be faked as if."
I have set up the react hook form but when I submit my form this is what I get in the dev tools tab network? Shouldn't be showing the user inputs at this point instead of empty string for all fields? The id is the only thing that gets updated.
Is there anything wrong with my Submit function or the actual fetch? Is it ok I have the POST fetch in this component where I have my form as well or should be in the same component where I have the GET request?
Would this one be a good way to approach the POST request?
const NewUserForm = () => {
const { register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = () => {
fetch(URL, {
method: 'POST',
body: JSON.stringify({
id:'',
name: '',
email: '',
address1:'',
address2:'',
city:'',
phone:''
}),
headers: {
'Content-type': 'application/json; charset=UTF-8'
},
})
.then((response) => response.json())
.then((json) => console.log(json));
}
return (
<>
<Header>New user</Header>
<FormContainer>
<Form onSubmit={handleSubmit(onSubmit)}>
<input type="text" placeholder="name" {...register("name", { required: true })} />
{errors.name && <span>This field is required</span>}
<input type="text" placeholder="email" {...register("email", { required: true })} />
{errors.email && <span>This field is required</span>}
<input type="text" placeholder="address1"{...register("address1", { required: true })} />
{errors.address1 && <span>This field is required</span>}
<input type="text" placeholder="address2"{...register("address2", { required: true })} />
{errors.address2 && <span>This field is required</span>}
<input type="text" placeholder="city"{...register("city", { required: true })} />
{errors.city && <span>This field is required</span>}
<input type="text" placeholder="phone"{...register("phone", { required: true })} />
{errors.phone && <span>This field is required</span>}
<input type="submit" />
</Form>
</FormContainer>
</>
);
}
Okay, after checking the react-hook-form docs, here is a possible solution:
In the docs, it says that your onSubmit will have a data param:
const onSubmit = (data) => alert(JSON.stringify(data));
Which means that you can use that in your onSubmit too.
Try changing your onSubmit to use the data parameter:
const onSubmit = (data) => {
fetch(URL, {
method: 'POST',
body: JSON.stringify(data),
And revert the change I suggested earlier regarding handleSubmit. This is correct:
<Form onSubmit={handleSubmit(onSubmit)}>

React form POST to Express server not working - REST

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.

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>
</>
)
}

Set state on form submit in a functional component

In my react typescript app - I have a login component and a handleLoginRequest function which sets the userMessage value:
function Login() {
let [userMessage, setUserMessage] = useState("");
return (
<form className="form-inline" onSubmit={(e) => {
setUserMessage(handleLoginRequest(e))
}} >
<label className="mr-sm-2">Email address:</label>
<input type="email" className="form-control mb-2 mr-sm-2" placeholder="Enter email" id="email" />
<label className="mr-sm-2">Password:</label>
<input type="password" className="form-control mb-2 mr-sm-2" placeholder="Enter password" id="password" />
<button type="submit" className="btn btn-primary mb-2">Submit</button>
{userMessage}
</form>
);
}
Update: handleLoginRequest is a API request
const handleLoginRequest = (event: any): any => {
event.preventDefault();
const data = {
email: event.target.email.value,
password: event.target.password.value
};
axios.post(`${process.env.REACT_APP_HTTP_PROXY}/api/v1/login`, data)
.then(res => {
console.log(res.data);
return res.data;
})
.catch(err => {
console.log(err);
return err.message;
});
}
Expected behavior:
When the form is submitted, the function setUserMessage(handleLoginRequest(e)) is called. I expect that it update the value of userMessage to login request received.
Actual result:
No change in the value of userMessage
What is the fix here?
Updated answer per the question modification
The issue is stemming from the fact you're trying to setState based on a axios post request. Axios requests are asynchronous, meaning they will happen out of order with the program control flow. Therefore, to solve this issue, it is important you only make a call to setUserMessage when the request is complete.
Example Code:
axios.post(`${process.env.REACT_APP_HTTP_PROXY}/api/v1/login`, data)
.then(res => {
setUserMessage(res.data);
})
.catch(err => {
// Do Something with error response
setUserMessage("Error: Something with the request went wrong.");
});
I will link a codesandbox to demonstrate:
https://codesandbox.io/s/focused-leakey-0jer4

Event code is not executed after default page reload

On onSubmit form event I'd like to send some data to the server with PUT or POST method and then refresh the page, but page reloads without executing the rest of the event code. Adding line event.preventDefault() fixes the issue but blocks reloading. What am I missing?
Event code:
handleFormSubmit = (event, requestType, articleID) => {
const title = event.target.elements.title.value;
const content = event.target.elements.content.value;
switch ( requestType ) {
case 'post':
return axios.post('http://127.0.0.1:8000/api/', {
title: title,
content: content
})
.then(res => console.log(res))
.catch(error => console.err(error));
case 'put':
return axios.put(`http://127.0.0.1:8000 /api/${articleID}/`, {
title: title,
content: content
})
.then(res => console.log(res))
.catch(error => console.err(error));
}
}
Form code:
<Form onSubmit={(event) => this.handleFormSubmit(
event,
this.props.requestType,
this.props.articleID )}>
<FormItem label="Title" >
<Input name="title" placeholder="Put a title here" />
</FormItem>
<FormItem label="Content" >
<Input name="content" placeholder="Enter some content ..." />
</FormItem>
<FormItem>
<Button type="primary" htmlType="submit">{this.props.btnText}</Button>
</FormItem>
</Form>
You need to programmatically reload your page after the form has been submitted successfully, or show an error message when there is no response or any server error:
class App extends React.Component {
handleSubmit = e => {
e.preventDefault();
return axios
.post("https://reqres.in/api/login", {
email: "title",
password: "content"
})
.then(res => {
alert(res.data.token);
location.reload();
})
.catch(error => console.log(error));
};
render() {
return (
<div className="App">
<form onSubmit={this.handleSubmit}>
<input type="text" placeholder="Email" />
<input type="password" placeholder="Password" />
<button type="submit">Submit</button>
</form>
</div>
);
}
}
Here is a demo :https://codesandbox.io/s/j7j00nq705
You can use event.preventDefault(). But you should use react-router library history.push() to manually load another component after your request completes.
case 'post':
return axios.post('http://127.0.0.1:8000/api/', {
title: title,
content: content
})
.then(res => {
console.log(res);
// using "history.push()" to load another component
this.props.history.push('/somePage')
})
.catch(error => console.err(error));
Your above Form component must be routed using react-router or Form component must be in a Component routed using react-router.

Resources