How to send form data from React to express - javascript

i'm fairly new in React. I'm trying to send register data to my backend from a from submit. I've tried the traditional method like setting post method and route in the form but that doesn't seem to work. Is there a way to send the data to back end then receive that data on the front end?
back end route: route is localhost:4000/api/users/register
router.post("/register", (req, res) => {
console.log(req.body)
console.log('Hit')
knex.select('*')
.from('users')
.where('email', req.body.email)
.then(function(results) {
knex('users')
.insert([{
first_name: req.body.first_name,
last_name: req.body.last_name,
phone: req.body.phone,
email: req.body.email,
password: bcrypt.hashSync(req.body.password, 15)
}])
.returning('id')
.then(function(id) {
req.session.user_id = id;
})
.catch(function(error) {
console.error(error)
});
}
})
.catch(function(error) {
console.error(error)
});
// }
});
React form code:
class Register extends Component {
constructor(props) {
super(props)
this.state = {
first_name: '',
last_name: '',
email: '',
password: '',
phone: ''
}
}
onChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
}
onSubmit = (e) => {
e.preventDefault();
// get form data out of state
const { first_name, last_name, password, email, phone } = this.state;
fetch('http://localhost:4000/api/users/register' , {
method: "POST",
headers: {
'Content-type': 'application/json'
}
.then((result) => {
console.log(result)
})
})
}
render() {
const { classes } = this.props;
const { first_name, last_name, password, email, phone } = this.state;
return (
<div className="session">
<h1>Create your Account</h1>
<div className="register-form">
<form method='POST' action='http://localhost:4000/api/users/register'>
<TextField label="First Name" name="first_name" />
<br/>
<TextField label="Last Name" name="last_name" />
<br/>
<TextField label="Email" name="email" />
<br/>
<TextField label="Password" name="password" />
<br/>
<TextField label="Phone #" name="phone" />
<Button type='Submit' variant="contained" color="primary">
Register
</Button>
</form>
</div>
</div>
);
}
}
export default Register;

You have to send the data in your state to the server, and you have to use the json method on the response from fetch in order to access it.
fetch('http://localhost:4000/api/users/register', {
method: "POST",
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify(this.state)
})
.then((response) => response.json())
.then((result) => {
console.log(result)
})

You have not posted the data to the api. Also there are few coding errors. You need update code from
fetch('http://localhost:4000/api/users/register' , {
method: "POST",
headers: {
'Content-type': 'application/json'
}
.then((result) => {
console.log(result)
})
To
fetch('http://localhost:4000/api/users/register' , {
method: "POST",
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify(this.state)
})
.then((result) => result.json())
.then((info) => { console.log(info); })

Try using a cool library called axios. this would be the tone down explanation.
On the frontend, you would use axios to post data to your backend:
const reactData = [{ id: 1, name:' Tom'}, { id: 2, name:' Sarah'}];
const url = localhost:4000/api/users/register;
let sendData = () => {
axios.post(url, reactData)
.then(res => console.log('Data send'))
.catch(err => console.log(err.data))
}
On the backend side, you'll receive that data, simply by doing something like:
const url = localhost:4000/api/users/register;
const usersData= [];
let getData = () => {
axios.get(url)
.then(res => usersData.push(res.data))
.catch(err => console.log(err.data))
}

Related

How to post a form with fetching?

I am trying to send a post with fetch an API.
My fetch is working because it returns 200 and sends the request but it sends an empty form.
It cannot take the values in the form input. Where is my mistake and how can I fix it?
...
const [contract, setContract] = useState("");
const form = useRef(null);
const submit = (e) => {
e.preventDefault();
const data = new FormData(form.current);
fetch(process.env.REACT_APP_ENDPOINT + "user/me/contract", {
method: "POST",
body: data,
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${localStorage.getItem("fray_access_token")}`,
},
})
.then((res) => res.json())
.then((json) => setContract(json.contract));
};
return( ...
<form ref={form} onSubmit={submit}>
<Input
required
type="text"
value={contract.name}
onChange={(e) =>
setContract({ ...contract, name: e.target.value })
}
/>
<Input
required
type="text"
value={contract.surname}
onChange={(e) =>
setContract({ ...contract, surname: e.target.value })
}
/>
<Input
required
type="email"
value={contract.emai}
onChange={(e) =>
setContract({ ...contract, email: e.target.value })
}
/>
</form>
...)
[Update]:
You can either remove the application/json header and let browser post the form data implicitly using the multipart/form-data content-type :
const submit = (e) => {
e.preventDefault();
const data = new FormData(form.current);
fetch(process.env.REACT_APP_ENDPOINT + "user/me/contract", {
method: "POST",
body: data,
headers: {
Authorization: `Bearer ${localStorage.getItem("fray_access_token")}`,
},
})
.then((res) => res.json())
.then((json) => setContract(json.contract));
};
As #Quentin pointed out, we cannot serialise FormData using JSON.stringify so it's better to use explicit function to do it for you:
const serialize = (data) => {
let obj = {};
for (let [key, value] of data) {
if (obj[key] !== undefined) {
if (!Array.isArray(obj[key])) {
obj[key] = [obj[key]];
}
obj[key].push(value);
} else {
obj[key] = value;
}
}
return obj;
}
const submit = (e) => {
e.preventDefault();
const data = new FormData(form.current);
fetch(process.env.REACT_APP_ENDPOINT + "user/me/contract", {
method: "POST",
body: typeof data !== 'string' ? JSON.stringify(serialize(data)): data,
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${localStorage.getItem("fray_access_token")}`,
},
})
.then((res) => res.json())
.then((json) => setContract(json.contract));
};
More details : https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

How to send form as PDF attached to email (Nodemailer, React, Node.js)

There is a React form. What I want to achieve: I fill out the form. I click on the submit button. Then this form should generate a PDF that is sent as an attachment through Nodemailer. I already achieved sending the email and generating the PDF (can download it), but I do not know how to attach that PDF to the email. There is a signature too, that I could already attach to the PDF. I just want this PDF to be sent as an attachment in the email. Now when I submit, it just downloads the PDF for me (which is good) and only sends a simple email (no PDF attachment).
Server:
app.post('/create-pdf', (req, res) => {
pdf.create(pdfTemplate(req.body), {}).toFile('result.pdf', (err) => {
if (err) {
res.send(Promise.reject());
}
res.send(Promise.resolve());
});
});
app.post('/api/contact', contact);
app.get('/fetch-pdf', (req, res) => {
res.sendFile(`${__dirname}/result.pdf`);
});
Nodemailer:
exports.contact = async (req, res) => {
const htmlEmail = `
<h1>Hello!</h1>
`;
const mailOptions = {
from: req.body.name,
to: 'xxxxxxxxxxxxxxxxxxx',
subject: 'Message',
html: htmlEmail,
attachments: [{}],
};
const transporter = nodemailer.createTransport({
host: 'smtp.ethereal.email',
port: 587,
auth: {
user: 'xxxxxxxxxxxxxxx',
pass: 'xxxxxxxxxxxxxxx',
},
});
transporter.sendMail(mailOptions, (err, data) => {
if (err) {
res.json({
status: 'fail',
});
} else {
res.json({
status: 'success',
});
}
});
return console.log('email sent');
};
Client:
class Contact extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
email: '',
phone: '',
message: '',
trimmedDataURL: null,
file: null,
};
}
sigPad = {};
clear = () => {
this.sigPad.clear();
};
trim = (e) => {
e.preventDefault();
this.setState({ trimmedDataURL: this.sigPad.getTrimmedCanvas().toDataURL('image/png') });
this.fileUpload(this.state.file).then((response) => {
console.log(response);
});
};
fileUpload(file) {
const url = 'http://localhost:3000/create-pdf';
const formData = new FormData();
formData.append('file', file);
const config = {
headers: {
'content-type': 'multipart/form-data',
},
};
return post(url, formData, config);
}
handleSubmit(e) {
e.preventDefault();
axios({
method: 'POST',
url: '/api/contact',
data: this.state,
}).then((response) => {
if (response.data.status === 'success') {
console.log('success');
} else if (response.data.status === 'fail') {
console.log('not success');
}
});
axios
.post('/create-pdf', this.state)
.then(() => axios.get('fetch-pdf', { responseType: 'blob' }))
.then((res) => {
const pdfBlob = new Blob([res.data], { type: 'application/pdf' });
saveAs(pdfBlob, 'newpdf.pdf');
});
}
render() {
return (
<div className="contact">
<h1>GET IN TOUCH</h1>
<div>
<form onSubmit={this.handleSubmit.bind(this)} method="POST">
<label htmlFor="name">NAME</label>
<br />
<input
onChange={this.onNameChange.bind(this)}
value={this.state.name}
type="text"
name="name"
placeholder="Your full name..."
/>
<br />
<label htmlFor="phone">PHONE</label>
<br />
<input
onChange={this.onPhoneChange.bind(this)}
type="text"
name="phone"
placeholder="Your phone number..."
value={this.state.phone}
/>
<br />
<label htmlFor="email">EMAIL</label>
<br />
<input
onChange={this.onEmailChange.bind(this)}
type="text"
name="email"
placeholder="Your email address..."
value={this.state.email}
/>
<br />
<label htmlFor="message">MESSAGE</label>
<br />
<textarea
onChange={this.onMessageChange.bind(this)}
type="text"
name="message"
value={this.state.message}
rows="5"
/>
<button className="contact-button" type="submit">
Send
</button>
<button onClick={this.createAndDownloadPdf}>download</button>
<br />
<SignatureCanvas
canvasProps={{ className: styles.sigPad }}
backgroundColor="gray"
ref={(ref) => {
this.sigPad = ref;
}}
/>
<img
alt=""
className={styles.sigImage}
src={this.state.trimmedDataURL}
style={{ width: '50px' }}
/>
<button className={styles.buttons} onClick={this.clear}>
Clear
</button>
<button
className={styles.buttons}
onClick={this.trim}
onChange={this.onFileChange.bind(this)}
>
Trim
</button>
</form>
</div>
</div>
);
}
onNameChange(event) {
this.setState({ name: event.target.value });
}
onEmailChange(event) {
this.setState({ email: event.target.value });
}
onPhoneChange(event) {
this.setState({ phone: event.target.value });
}
onMessageChange(event) {
this.setState({ message: event.target.value });
}
onFileChange(e) {
this.setState({ file: e.target.files[0] });
}
}
export default Contact;
attachments: [
{
filename: 'result.pdf',
path: '../grovespine/result.pdf',
},
],
a new result.pdf is always generated in my folder and just attach that to the nodemailer

pots API [object object ] in react native

I had a problem sending data to the server.
when I try to submit data via postman successfully with the response below
and if I activate
'Content-Type': 'application / json'
i have a problem that is
JSON Parse error: Unrecognized token '<'
{
"status": 200,
"message": "success login",
"id_kurir": "3",
"username": "tester",
}
When I try with code, I get an error that is [object object]
this my code :
constructor(props) {
super(props);
this.state = {
Uname : '',
Upass : ''
}
}
login= ()=>{
const {Uname,Upass} = this.state;
fetch('https://example.com/login', {
method: 'POST',
// headers: {
// 'Accept' : 'application/json',
// 'Content-Type': 'application/json'
//},
body: JSON.stringify({
username: Uname,
password: Upass
})
})
.then((response) => response.json())
.then((responseJson) => {
alert(responseJson);
console.log(JSON.stringify(responseJson));
}).catch((error)=>{
console.log(error);
})
Keyboard.dismiss();
}
<Form style={styles.mainForm}>
<Item style={styles.formItems}>
<Input placeholder="Username" style={styles.Input} onChangeText={Uname => this.setState({Uname})}/>
</Item>
<Item style={styles.formItems}>
<Input style={styles.Input} secureTextEntry={true} onChangeText={(Upass) => this.setState({Upass})}/>
</Item>
<View style={styles.Button}>
{/* <Button block style={styles.mainBtn} onPress={() => this.props.navigation.navigate('home')}> */}
<Button block info style={styles.mainBtn} onPress={this.login}>
<Text style={styles.btnText}>Submit</Text>
</Button>
</View>
</Form>
where is the fault?
The server probably a 404 or 500 error. Instead of response.json() use response.text() you will get the html in text.
I assume Your server is not taking JSON formatted body
Try using below code.
Option 1:
fetch('https://example.com/login', {
method: 'POST',
body: JSON.stringify({
username: Uname,
password: Upass
})
}).then(response => response.text()).then((text) => {
if (Platform.OS === 'android') {
text = text.replace(/\r?\n/g, '').replace(/[\u0080-\uFFFF]/g, '');
// If android, remove unwanted chars.
}
return text;
}).then(response => JSON.parse(response));
Option 2:
fetch('https://example.com/login', {
method: 'POST',
body: JSON.stringify({
username: Uname,
password: Upass
})
}).then((response) => response.text()).then((responseJson) => {
alert(JSON.stringify(responseJson));
console.log(JSON.stringify(responseJson));
}).catch((error) => {
alert(JSON.stringify(error));
console.log(error);
})

"Cannot POST /" in Vue (Gridsome) App - Netlify Forms prevent redirect

I am building a personal website with Gridsome. I am trying to set up a newsletter signup form via Netlify Forms. I don't want the user to be redirected after clicking 'Submit'. To prevent that I use #submit.prevent like so:
<form name= "add-subscriber" id="myForm" method="post" #submit.prevent="handleFormSubmit"
data-netlify="true" data-netlify-honeypot="bot-field">
<input type="hidden" name="form-name" value="add-subscriber" />
<input type="email" v-model="formData.userEmail" name="user_email" required="" id="id_user_email">
<button type="submit" name="button">Subscribe</button>
</form>
Then using a mix of the following guides (gridsome guide, CSS-Tricks guide) I do the following in my script section:
<script>
import axios from "axios";
export default {
data() {
return {
formData: {},
}
},
methods: {
encode(data) {
return Object.keys(data)
.map(key => encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))
.join('&')
},
handleFormSubmit(e) {
axios('/', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: this.encode({
'form-name': e.target.getAttribute('name'),
...this.formData,
}),
})
.then(() => this.innerHTML = `<div class="form--success">Almost there! Check your inbox for a confirmation e-mail.</div>`)
.catch(error => alert(error))
}
}
}
</script>
Error
Whatever I try I can't figure out how to configure the desired behavior. I keep getting the following errors - > Error: Request failed with status code 404 & Cannot POST /
Note
The reason I want to do it this way is that after the user submits the form a Netlify Function will be called to send the email_adress to EmailOctopus via their API.
This is how the function looks like:
submissions-created.js
import axios from "axios";
exports.handler = async function(event) {
console.log(event.body)
const email = JSON.parse(event.body).payload.userEmail
console.log(`Recieved a submission: ${email}`)
axios({
method: 'POST',
url: `https://emailoctopus.com/api/1.5/lists/contacts`,
data: {
"api_key": apikey,
"email_address": email,
},
})
.then(response => response.json())
.then(data => {
console.log(`Submitted to EmailOctopus:\n ${data}`)
})
.catch(function (error) {
error => ({ statusCode: 422, body: String(error) })
});
}
Sorry for the long question. I really apreciate your time and your help. If you need any further details please let me know.
You can see the functional implementation in my repo (https://github.com/rasulkireev/gridsome-personal-webite). These are the changes I made.
submission-created.js
var axios = require("axios")
exports.handler = async function(event, context) {
const email = JSON.parse(event.body).payload.email
console.log(`Recieved a submission: ${email}`)
return await axios({
method: 'POST',
url: 'https://api.buttondown.email/v1/subscribers',
headers: {
Authorization: `Token ${process.env.BUTTONDOWN_API}`
},
data: {
'email': email,
},
})
.then(response => console.log(response))
.catch(error => console.log(error))
}
newsletter form in my components
<div>
<form
name="add-subscriber"
id="myForm"
method="post"
data-netlify="true"
data-netlify-honeypot="bot-field"
enctype="application/x-www-form-urlencoded"
#submit.prevent="handleFormSubmit">
<input type="hidden" name="form-name" value="add-subscriber" />
<input type="email" name="userEmail" v-model="formData.userEmail">
<button type="submit" name="button">Subscribe</button>
</form>
</div>
with the following script code in the same component
import axios from "axios";
export default {
props: ['title', 'description'],
data() {
return {
formData: {
userEmail: null,
},
}
},
methods: {
encode(data) {
const formData = new FormData();
for (const key of Object.keys(data)) {
formData.append(key, data[key]);
}
return formData;
},
handleFormSubmit(e) {
const axiosConfig = {
header: { "Content-Type": "application/x-www-form-urlencoded" }
};
axios.post(
location.href,
this.encode({
'form-name': e.target.getAttribute("name"),
...this.formData,
}),
axiosConfig
)
.then(data => console.log(data))
.catch(error => console.log(error))
.then(document.getElementById("myForm").innerHTML = `
<div>Thank you! I received your submission.</div>
`)
}
}
}

User.id is undefined

I'm building a website where users can register, but when registration is complete nothing happens, its supposed to enter the site.
I have tested it with console.log and found out that my user.id is undefined.
this is my register on the server side:
const handleRegister = (req, res, db, bcrypt) => {
const { email, name, password } = req.body;
if (!email || !name || !password) {
return res.status(400).json('incorrect form submission');
}
const hash = bcrypt.hashSync(password);
db.transaction(trx => {
trx.insert({
hash: hash,
email: email
})
.into('login')
.returning('email')
.then(loginEmail => {
console.log(email)
return trx('users')
.returning('*')
.insert({
email: email,
name: name,
joined: new Date()
})
.then(user => {
res.json(user[0]);
})
})
.then(trx.commit)
.catch(trx.rollback)
})
.catch(err => res.status(400).json('unable to register ' + err))
}module.exports = {
handleRegister: handleRegister
};
and this is my register on the frontend:
import React from 'react';
class Register extends React.Component {
constructor(props){
super(props);
this.state = {
name: '',
email: '',
password: ''
}
}
onNameChange = (event) => {
this.setState({name: event.target.value})
}
onEmailChange = (event) => {
this.setState({email: event.target.value})
}
onPasswordChange = (event) => {
this.setState({password: event.target.value})
}
onSubmitSignIn = () => {
fetch('http://localhost:3000/register', {
method: 'post',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
name: this.state.name,
email: this.state.email,
password: this.state.password
})
})
.then(response => response.json())
.then(user => {
console.log(user.id);
if (user.id) {
console.log(user, user.id);
this.props.loadUser(user)
this.props.onRouteChange('home');
}console.log(user.id);
})
}
It is on the frontend I have set the console.log and it never enters the if statement.
How do I fix this?
If you are using mongodb the id field is defined as _id

Categories

Resources