Passing data from front end to route in backend React - reactjs

I am currently new to using React and express, I wish to send data which i have received from a form. The data i would like to send back is the UserInfo or email which is in the state. However I am extremely unsure how I am supposed to go about this request.
class ForgotPassword extends Component {
constructor() {
super()
this.state = {
email:'',
}
this.handleSubmit = this.handleSubmit.bind(this)
this.handleChange = this.handleChange.bind(this)
}
componentDidMount = () =>{
// this.fetchUserInfo();
}
handleChange = (e) => {
this.setState ({
[e.target.id]: e.target.value
})
console.log(this.state);
}
handleSubmit = async (e) => {
e.preventDefault();
const userInfo = {
email : this.state.email
};
fetch("/forgotpassword", {
method: "POST",
body: JSON.stringify(userInfo),
headers: { "Content-Type": "application/json" }
})
.then(response => {
return response.json();
})
.then(jsonData => {
console.log(jsonData);
})
.catch(err => {
console.log("Error with data fetch " + err);
});
};
This is my form...
<div className='row'>
<div className='col'></div>
<div className='col card form'>
<h1 id="title">Reset Password</h1>
<h5 id="passinstruc">Please enter your email to reset your password</h5>
<form id="forgotpass" onSubmit={this.handleSubmit}>
<div className="form-group">
<label htmlFor="exampleInputEmail1">Email </label>
<input onChange={this.handleChange} type="email" className="form-control" id="email" aria-describedby="emailHelp" placeholder="Enter email" value={this.state.email} />
<small id="emailHelp" className="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<button id="loginbtn" type="submit" className="btn btn-primary btn-lg btn-block" >Submit</button>
<br/>
<div className='division'>
<Link to="/register" className='btn btn-primary btn-lg btn-block' id="registerbtn" > Create your account here</Link>
</div>
</form>
</div>
In my backend I am getting a POST /forgotpassword 404 message but I dont know why. Help would be much appreciated.
This is my backend route where I will be sending the information
var express = require('express');
var router = express.Router();
var connection = require ('../connection');
var email = require ('./sendEmail');
router.post('/forgotpassword', function(req, res, next) {
console.log(req.email);
var userEmail = req.email;
var text = "Follow the instructions below to reset your password"
email.sendEmailWithTemplate(userEmail,'PetS.o.S Password Reset', text);
});

For sending data you will need the domain name or ip address of your server.
Once you obtained that, you can use jQuery.get - https://api.jquery.com/jQuery.get/
or jQuery.post -
https://api.jquery.com/jQuery.post/
Or if you are not using jQuery, use XMLHttpRequest -
https://www.w3schools.com/xml/xml_http.asp

Instead of sending data in body send it in response.
https://www.freecodecamp.org/news/create-a-react-frontend-a-node-express-backend-and-connect-them-together-c5798926047c/
fetch('/api/getList')
.then(res => res.json())
.then(list => this.setState({ list }))
https://dev.to/nburgess/creating-a-react-app-with-react-router-and-an-express-backend-33l3

Related

Why am I getting a Nodemailer Cannot /POST error?

I wrote a code for a contact us form on nodemailer and I am getting a cannot /post error. What could be the problem? I set up a mailtrap account but listed my email as my regular email. I am not used to using react or node.js so I am having a hard time understanding this. Here is my code:
for contact_us.js:
import React from "react";
import "./contactus.css"
import axios from 'axios';
export default class ContactUs extends React.Component {
state = {
name: '',
subject: '',
email: '',
message: ''
}
constructor(props) {
super(props);
this.onEmailChange= this.onEmailChange.bind(this);
this.onMsgChange= this.onMsgChange.bind(this);
this.onNameChange= this.onNameChange.bind(this);
this.onSubjectChange= this.onSubjectChange.bind(this);
this.submitEmail= this.submitEmail.bind(this);
}
render() {
return (
<div className="section">
<div className="container">
<div className="row">
<div className="col-md-12">
<div className="section-title">
<h2 className="title">Contact Us</h2>
<p>Let us know what you think! </p><hr/>
<form id="contact-form"
method="POST">
<div className="form-group">
<div className="row">
<div className="col-md-6">
<input placeholder = "Name" id="name" type="text"
className="form-control" required value={this.state.name}
//onChange={this.onNameChange.bind(this)}/>
onChange= {this.onNameChange}/>
</div>
<div className="col-md-6">
<input placeholder = "Email" id="email" type="email"
className="form-control" aria-describedby="emailHelp"
required value={this.state.email}
//onChange=
//{this.onEmailChange.bind(this)}
onChange= {this.onEmailChange}
/>
</div>
</div>
</div>
<div className="form-group">
<input placeholder = "Subject" id="subject" type="text"
className="form-control" required value={this.state.subject}
//onChange={this.onSubjectChange.bind(this)}
onChange= {this.onSubjectChange}/>
</div>
<div className="form-group">
<textarea placeholder = "Message" id="message"
className="form-control" rows="1"
required value={this.state.message}
//onChange= {this.onMsgChange.bind(this)}
onChange={this.onMsgChange}/>
</div>
<button className= "button" type="submit" id="button" onSubmit={this.submitEmail} >Submit</button>
</form>
</div>
</div>
</div>
</div>
</div>
);
}
onNameChange(event) {
this.setState({name: event.target.value})
}
onEmailChange(event) {
this.setState({email: event.target.value})
}
onSubjectChange(event) {
this.setState({subject: event.target.value})
}
onMsgChange(event) {
this.setState({message: event.target.value})
}
submitEmail(e){
console.log('submitting');
e.preventDefault();
axios({
method: "POST",
url:"localhost:3000/contact_us",
data: this.state
}).then((response)=>{
if (response.data.status === 'success'){
alert("Message Sent.");
this.resetForm()
}else if(response.data.status === 'fail'){
alert("Message failed to send.")
}
})
}
resetForm(){
this.setState({name: '', email: '',subject:'', message: ''})
}
}
for index.js:
var express = require('express');
var router = express.Router();
var nodemailer = require('nodemailer');
require('dotenv').config();
var cors = require('cors');
const creds = require('./config');
var app= express();
const port= 4000;
app.use((request, response, next) => {
response.header("Access-Control-Allow-Origin", "*");
response.header("Access-Control-Allow-Headers", "Content-Type");
next();
});
const transporter = nodemailer.createTransport({
host: 'smtp.mailtrap.io',
port: 2525,
auth: {
user: '',
pass: ''
}
});
transporter.verify(function(error, success) {
if (error) {
console.log(error);
} else {
console.log("Server is ready to take our messages");
}
});
app.post('/contact_us', (req, res, next) => {
var name = req.body.name
var email = req.body.email
var subject = req.body.subject
var message = req.body.message
var mail = {
from: name,
to: '',//my regular email I used to sign up to mailtrap
subject: subject,
text: message
}
transporter.sendMail(mail, (err, data) => {
if (err) {
console.log('failed');
res.json({
status: 'fail'
})
} else {
console.log('successful');
res.json({
status: 'success'
})
}
})
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
First spot:
Add HTTP to the URL "http://localhost:3000/contact_us" and change the port to 4000 since the API is working under such port. Check if this is enough to get it working

Why does my Nodemailer POST request work in postman but not from my react front-end?

I am using the Nodemailer package and a SendinBlue smtp email server to create a website contact form. When I send a request using postman the email sends and everything works as it should, however, when I try an Axios post request from my react front-end (in both production and live environments) I get the following:
POST http:///send 404 (Not Found)
My Server.js file:
const express = require("express");
const app = express();
const PORT = process.env.PORT || 3001;
const nodemailer = require('nodemailer')
require('dotenv').config();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
if (process.env.NODE_ENV === "production") {
app.use(express.static(path.join(__dirname, 'build')));
}
// Catch all route to redirect unmanaged routes back to the react app.
// THIS OPTION IS NOT SEO OPTIMIZED
// THIS ROUTE SENDS ALL SAVED LINKS TO THE ROOT
app.get('/*', function (req, res) {
res.redirect('/')
});
// CONNECTION NOT YET TESTED
// Nodemailer config to handle contact form submit.
let transporter = nodemailer.createTransport({
host: "smtp-relay.sendinblue.com",
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS,
},
});
// Post route for contact form submission
app.post('/send', (req, res) => {
console.log(req.body)
var { name, email, message } = req.body;
let mailOptions = {
from: `"${name}" <${email}>`, //'"Fred Foo 👻" <foo#example.com>', sender address
to: `${process.env.EMAIL}`, // list of receivers
subject: "Atlas Pet Contact Form",
text: `${message}`, // plain text body
}
transporter.sendMail(mailOptions, function (err, data) {
if (err) {
console.log('Error: ', err)
} else {
console.log('Email Sent')
}
});
res.json('Email Sent');
});
app.listen(PORT, () => { console.log(`API Server now listening on PORT ${PORT}!`) })
React contact component:
import React, { useState } from "react";
import axios from "axios";
import "../../pages/style.css";
function ContactForm() {
const [formData, setFormData] = useState({
name: "",
email: "",
message: ""
});
function sendEmail(e) {
e.preventDefault();
axios.post("/send", formData)
.then(res => {
console.log(res)
console.log(res.data)
})
.catch(err => {
console.log(err)
})
};
function handleNameChange(e) {
setFormData({ ...formData, name: e.target.value })
};
function handleEmailChange(e) {
setFormData({ ...formData, email: e.target.value })
};
function handleMessageChange(e) {
setFormData({ ...formData, message: e.target.value })
};
return (
<div className="jumbotron form-spacing">
<form className="form">
<h1 className="display-4 main-txt"><strong>Drop a Line</strong></h1>
<br/>
<div className="hr"></div>
<br/>
<p className="lead main-txt">Questions, Comments, Concerns? Let us know!</p>
{/* Name input */}
<label htmlFor="name">Name</label>
<input
className="inputs"
type="text"
id="name"
name="name"
onChange={handleNameChange}
></input>
<br />
{/* Email input */}
<label htmlFor="email">Email</label>
<input
className="inputs"
type="email"
id="email"
name="email"
onChange={handleEmailChange}
></input>
<br />
{/* Message input */}
<label htmlFor="message">Message</label>
<textarea
className="inputs"
rows="6"
id="message"
name="message"
onChange={handleMessageChange}
></textarea>
{/* Submit button */}
<button
className="submit-btn btn btn-light btn-submit"
type="submit"
value="Send Message"
onClick={sendEmail}
>Send Message</button>
</form>
<div className="row-overlay"></div>
</div>
)
}
export default ContactForm;

unable to display response from post request in react

i am new to react development.
I am able to get response from post request and print in console but nt sure how to display it on main page.
code from app.js for my ui
render() {
return (
<div className="App">
<h1>Enter Email Address to Verify</h1>
<h1>{this.state.response.body}</h1>
<form onSubmit={this.handleSubmit}>
<p>
<strong>Address:</strong>
</p>
<input
type="text"
value={this.state.post}
onChange={e => this.setState({ post: e.target.value })}
/>
<button type="submit">check</button>
</form>
</div>
);
}
this is the way i get it print on console
console.log(wellFormed, validDomain, validMailbox);
handleSubmit = async e => {
e.preventDefault();
const response = await fetch('/api/v1/verifier', {
method: 'POST',
// body: this.state,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ post: this.state.post }),
});
const body = await response.text();
this.setState({ responseToPost: body });
};
From verifier method
res.send(
`response received , welllformed = ${wellFormed}, validDomain = ${validDomain}, validMailbox = ${validMailbox}`,
)
Most of the time you will get a JSON response which is nothing but an Array of objects. So you can put that to a state then use higher order function map to render each element to the Dom.
let's assume that your response is like this.
[{"activeCases":"5132472","country":"USA"} ,"activeCases":"455602","country":"India"}]
you can refer each object as course(it can be any name) inside the map method.
{this.state.response.map((course) => (
<div>
<h3>Active cases :{course.activeCases}</h3>
<h5>country :{course.country}</h6>
</div>
))}
This will render each data in your repose to the Dom like thise.
Active cases :5132472
country :USA
Active cases :455602
country :India
render() {
return (
<div className="App">
<h1>Enter Email Address to Verify</h1>
<h2>{this.state.response.body}</h2>
<form onSubmit={this.handleSubmit}>
<p>
<strong>Email Address:</strong>
</p>
<input
type="text"
value={this.state.post}
onChange={e => this.setState({ post: e.target.value })}
/>
<button type="submit">Verify</button>
</form>
<p>{this.state.responseToPost}</p>
</div>
);
}
This worked for me

Redirection to dashboard after login in react

I have a login page, and I want to redirect users to dashboard after the details are filled.
I have tried using history.push and redirect components but I couldn't redirect.
Login Page
class Login extends React.Component {
state = {
email: '',
password: '',
errors: {},
redirect: false
}
validateForm = () => {
let errors = {};
let formIsValid = true;
if(!this.state.email) {
formIsValid = false;
errors['email'] = 'Please enter email to continue';
}
if(!this.state.password) {
formIsValid = false;
errors['password'] = 'Please enter password to continue';
}
this.setState({
errors: errors
})
return formIsValid;
}
handleChange = (event) => {
this.setState({
[event.target.id]: event.target.value
});
}
handleSubmit = (event) => {
event.preventDefault();
// console.log(this.state);
if(this.validateForm()) {
const loginData = {
email: this.state.email,
password: this.state.password
}
axios
.post('/users.json', loginData)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
})
}
}
render() {
return (
<div className="container">
<form onSubmit={this.handleSubmit} className="white">
<h5 className="grey-text text-darken-3">Login</h5>
<div className="input-field">
<label htmlFor="email">Email</label>
<input type="email" id="email" onChange={this.handleChange} />
<p>{this.state.errors.email}</p>
</div>
<div className="input-field">
<label htmlFor="password">Password</label>
<input type="password" id="password" onChange={this.handleChange} />
<p>{this.state.errors.password}</p>
</div>
<div className="input-field">
<button onClick={this.redirectHandler} className="btn btn-primary">Login</button>
</div>
</form>
</div>
)
}
}
export default Login;
I want to redirect to other page once the form is submitted with the email and password.
I've been trying this for days but I couldn't find a solution.
import { withRouter } from 'react-router';
class Login extends React.Component {
state = {
email: '',
password: '',
errors: {},
redirect: false
}
validateForm = () => {
let errors = {};
let formIsValid = true;
if(!this.state.email) {
formIsValid = false;
errors['email'] = 'Please enter email to continue';
}
if(!this.state.password) {
formIsValid = false;
errors['password'] = 'Please enter password to continue';
}
this.setState({
errors: errors
})
return formIsValid;
}
handleChange = (event) => {
this.setState({
[event.target.id]: event.target.value
});
}
handleSubmit = (event) => {
event.preventDefault();
// console.log(this.state);
if(this.validateForm()) {
const loginData = {
email: this.state.email,
password: this.state.password
}
axios
.post('/users.json', loginData)
.then(response => {
this.props.history.push("/dashboard");
console.log(response.data);
})
.catch(error => {
console.log(error);
})
}
}
render() {
return (
<div className="container">
<form onSubmit={this.handleSubmit} className="white">
<h5 className="grey-text text-darken-3">Login</h5>
<div className="input-field">
<label htmlFor="email">Email</label>
<input type="email" id="email" onChange={this.handleChange} />
<p>{this.state.errors.email}</p>
</div>
<div className="input-field">
<label htmlFor="password">Password</label>
<input type="password" id="password" onChange={this.handleChange} />
<p>{this.state.errors.password}</p>
</div>
<div className="input-field">
<button onClick={this.redirectHandler} className="btn btn-primary">Login</button>
</div>
</form>
</div>
)
}
}
export default withRouter(Login);
have some complain about your code.
first: for form validation and handling you dont need to use state,
there is a library called Formik which will help you a lot with
this.
second: if you are using redux to check user is logged in or
not you need to create a private route for routes which cannot be
accessible for public like here dashboard component.
third: to use history you need to wrap your
component inside withRouter HOC which will pass route props to your
component so you can use history or if your are using functional component you can use useHistory() hook.

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

Resources