I'm doing a React web site, with a node.JS REST Api, and actually there is something that I don't know how to do.
When I'm logging in, my React form make a POST request to my Api (considering it's a School Project so I'm working locally, my React app is on port 3000 and my Api is on port 8080), and when I'm submiting, I'm redirected on the response of my Api.
I'd like to be redirected to a page of my React App and receive the response of my Api (when I'm using res.redirect() I have the React page but not the Api response).
Did somebody know how to do it ?
Here is my React Form Component:
class Form extends Component{
constructor(){
super()
this.location = window.location.href
}
render(){
return(
<form action="http://localhost:8080/login" method="post">
<label for="identifier">Mail:</label>
<br/>
<input type="email" id="identifier" name="identifier"/>
<br/><br/>
<label for="password">Password:</label>
<br/>
<input type="password" id="password" name="password"/>
<input id="locator" name="locator" value={this.location} type="hidden"/>
<br/><br/><br/>
<button type="submit">Se connecter</button>
</form>
)
}
}
And here is my Api login route :
app.post('/login', (req, res) => {
console.log(req.body.identifier);
console.log(req.body.password);
client.connect().then(() => {
let newUser = { identifier: req.body.identifier}
return client.db(`${process.env.MONGODB}`).collection(`${process.env.MONGOCOLLECTION}`)
.findOne(newUser)
.then(
result => {
if(result == null){
console.log("No user found");
return res.status(401).json({ error: 'Utilisateur non trouvé !' });
}else{
console.log("User "+result.name+" "+result.firstName+" found");
if(req.body.password !== cryptr.decrypt(result.password)){
console.log("Mot de passe incorrect !");
return res.status(401).json({ error: 'Mot de passe incorrect !' });
}else{
const token = jwt.sign({
id: result._id,
username: result.identifier
}, "my_secret", { expiresIn: '3 hours' })
console.log(token)
return res.json({ access_token: token })
}
}
},
err => res.status(500).json({ err }),
);
})
.then(() => {
console.log("--------------------------------");
})
res.redirect(req.body.locator)
})
You can use XHR requests to handle API calls to server and fetching back data to render in your React component.
Instead of using action in form,
use
<form onSubmit={this.handleSubmit}>
and define a method which handles the submit logic.
async handleSubmit(e) {
const reponse = await
fetch('http://localhost:8080/login', {
method: 'POST',
mode: 'cors', //as your server is on different origin, your server will also have to enable CORS
body: JSON.stringify(formData) //formData will have to be extracted from your input elements before sending to server
})
const data = response.json() //This is the data from your server which you'll get without the need of redirecing.
}
fetch is the default js library to handle XHR request.
There are others as well like axios.
Related
I have tried a few different ways of doing this but no matter what I've tried I get the same result.
Once I start the server, the first time I post, it doesn't work. because the state hasn't updated (I think)? All of the following post requests afterwards work fine, along with the correct state. So I'm not so sure it's state. Here's my code
Register.js
export default class Register extends React.Component{
constructor(props){
super(props);
this.state = {
username: '',
password: ''
}
}
onChange = (e) => this.setState({[e.target.name]: e.target.value});
register = async () => {
await axios.post(config.API_URI + 'register', {
username: this.state.username,
password: this.state.password
});
}
render(){
return(
<div>
<form id='register-form' className='border'>
<div id='form-title'>Create account</div>
<div className='mb-3'>
<label className='form-label' htmlFor='username-label' name='username-label'>Username</label>
<input type='text' className='form-control' id='usernameInput' name='username' onChange={this.onChange}></input>
</div>
<div className='mb-3'>
<label className='form-label' htmlFor='password-label' name='password-label'>Password</label>
<input type='password' className='form-control' id='password-input' name='password' onChange={this.onChange}></input>
</div>
{/*}
<div className='mb-3'>
<label className='form-label' htmlFor='password-label-confirm' name='password-label-confirm'>Confirm Password</label>
<input type='password' className='form-control' id='password-input-confirm' name='passwordConfirm'></input>
</div>
{*/}
<div id='buttons'>
<button className='btn btn-primary' id='register-btn' onClick={this.register} disabled={this.state.username === '' & this.state.username === ''}>Register</button>
<Link className='btn btn-primary' to='/login' id='login-btn'>Login</Link>
</div>
</form>
</div>
)
}
}
server.js post request (currently just attempting to console.log my request instead of adding to my database). I have gotten it to save to the database just fine following the second post attempt.
...
app.post("/register", (req, res)=>{
try{
if(req.body){
console.log(req.body);
/*
User.find({username: req.body.username}, (err, data)=>{
if(data.length == 0){
let user = new User({
username: req.body.username,
password: req.body.password
});
user.save((err,data)=>{
if(err){
res.status(400).json({
errorMessage: err,
status: false
});
} else {
res.status(200).json({
status: true,
title: 'Registered Successfully'
});
}
});
}
});
*/
}
} catch(e){
res.status(400).json({
errorMessage: 'Something went wrong!',
status: false
})
}
});
I'm a beginner making my first full-stack application
Good night! I cannot comment because I'm too new to Stack Overflow, so I'll say the following as an answer:
I ran your code on my machine and it worked fine but the reload. When I clicked on the "Register" button, I read the current state value by adding console.log(this.state) just before await axios.post(...).
That worked since the first click. However, the page reloads each submition. You missed the event.preventDefault(). This function prevents the reload when submitting a form by clicking on a button inside it. This is the code:
register = async (event) => {
event.preventDefault();
await axios.post('http://localhost:3333/register', {
username: this.state.username,
password: this.state.password
});
}
Then, I ran a Node API with your code. It also console.log(req.body) worked perfectly fine as well.
Therefore, I don't have any other ideas of what could be causing the issue on your machine besides the missing event.preventDefault().
P.S.:
Some features that helps while debugging JavaScript:
Use the command debugger; on your Front-End code. For example, inside the register method. This allows you to stop the execution of the code and inspect all the variables available and their current values. This may help you.
While debugging don't forget to put a lot of console.log on your code in specific parts that could be related to your bug. This helps you understand what's going on.
I am currently working on an application with node.js, express and ReactJs. I am also using sequelize as my ORM. I was working on my form which originally sent nulls to my database and since then I have been stuck on this error for a few days. I am getting the following on my frontend ReactJs:
TypeError: Cannot read property 'prototype' of undefined'
I know this error is very vague and happens for many reasons. For me it happened when I was working on my form.I am using useStates to set my values and using axios to handle the post request.
Where I declared my states:
let [state, setState] = useState({
leadName: "",
excellentLead: ""
});
handleChange(evt) function:Used to handle changes based on my input.
function handleChange(evt) {
const value = evt.target.value;
axios({
method: "post",
url: "http://localhost:5000/add",
data: body,
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
setState({
...state,
[evt.target.name]: evt.target.value,
});
Current form(I am using React Bootstrap for styling.):
<Form onSubmit={handleChange}>
<Form.Group controlId="formBasicName">
<Form.Label>Name</Form.Label>
<Form.Control
type="text"
placeholder="Enter Name"
name="leadName"
value={state.leadName}
onChange={handleChange}
/>
</Form.Group>
<Form.Group controlId="formBasicFollowUp">
<Form.Label>
Excellent Lead Worth following up(Yes/No/Maybe)
</Form.Label>
<Form.Control
type="text"
placeholder="Enter Name"
name="excellentLead"
value={state.excellentLead}
onChange={handleChange}
/>
</Form.Group>
<Button variant="primary" type="submit">
Submit
</Button>
</Form>
In my server.js this is my post route:
app.post('/add', function(request, response) {
Information.create({
Name:req.body.leadName,
ExcellentLeadWorthFollowingUp:req.body.excellentLead
}).then(function(Information){
res.json(Information);
})
})
I don't have any issues connecting to the database from the front end and my post method used to send nulls on a button click which wasn't the goal. To add, this error broke my entire program.
Any suggestions, explanations or links would be appreciated!
Since you have fixed your error, I would like to make you aware that you are calling handleChange every time your input changes. This means you are making a POST request every time you type a character in your input.
A better approach would be to only do your post on submit.
import React, { useState } from "react";
const App = () => {
const [data, setData] = useState({ name: "", age: "" });
const handleChange = (e, field) => {
e.preventDefault(); // prevent the default action
// set your data state
setData({
...data,
[field]: e.target.value
});
};
const handleSubmit = (e) => {
e.preventDefault();
// axios post data
console.log(data); // just for showing
};
return (
<div>
<p>Fill in data</p>
<form onSubmit={handleSubmit}>
<input
type="text"
value={data.name}
onChange={(e) => handleChange(e, "name")}
/>
<input
type="text"
value={data.age}
onChange={(e) => handleChange(e, "age")}
/>
<button type="submit">SUBMIT</button>
</form>
</div>
);
};
export default App;
import { response } from 'express';
Was imported and that caused the error this whole time....A classic.
I have the following component:
const WaitingListComponent = () => {
const [email, setEmail] = useState('')
const onSubmit = (e) => {
e.preventDefault()
axios.post("/api/waiting-list/addToList", {
email: email
})
}
return (
<form className="waiting-list-component-container" onSubmit={onSubmit}>
<h4 className="waiting-list-component-heading">Join our waiting list to get early access</h4>
<p className="waiting-list-component-paragraph">Join our waiting list to get exclusive early access to our platform when we're ready to launch.</p>
<input className="waiting-list-component-input" name="email" type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="janedoe#email.com" />
<GeneralButton type="submit" text="Get access" />
</form>
)
}
This Axios request is getting posted via the following function:
const MailerLite = require('mailerlite-api-v2-node').default;
const mailerLite = MailerLite(process.env.MAILER_API);
module.exports = (req, res) => {
res.statusCode = 200;
res.setHeader("Content-Type", "application/json");
const email = req.body.email;
mailerLite.addSubscriberToGroup(process.env.MAILER_GROUP, email)
.then(() => {
console.log("Successfully sent new subscriber to MailerLite.");
res.send(JSON.stringify({ success: true }));
})
.catch((err) => {
console.log("There was an error.");
console.log(err);
res.send(JSON.stringify({ success: false }));
});
};
This is a post to a website called 'MailerLite'.
Their documentation is here: https://developers.mailerlite.com/docs/getting-started-with-mailerlite-api
And the package I'm using to post via node is here: https://www.npmjs.com/package/mailerlite-api-v2-node#addsubscribertogroupgroupid-subscriber
I'm attempting to use the 'addSubscriberToGroup' function to add a new subscriber to my group.
However, despite the Axios post successfully going through - as shown in the error message - there is an error being generated each time.
I don't want to post the full error because it's lengthy and it contains the API key, but the final two lines indicate it's an Axios error:
isAxiosError: true
Can anyone point out where I'm going wrong here?
If you need more info, or have any specific questions, please let me know!
The issue is probably that you need to send email as an object. You could do it like this: addSubscriberToGroup('id', { email: email })
I've been working on a node js/express js app for some time now. I have get's and post's that work from jquery $ajax calls.
For some reason I have one post "loginUser" that isn't getting into the user route post method
This was working previously but now has stopped, and as any programmer would say "has stoppped working for some reason".
I don't beleive anything was changed. I've tried using GET's, new POST's names, etc.
Every time it only provides a 500 error without any information in the error object.
Loginpage.ejs Form:
<form class="form-horizontal" id="loginUserForm" >
<div class="controls">
<strong>Email</strong><br/><input type="email" class="form-control custom-input-width" id="login-email" value="adrian#adriannadeau.com" required>
</div>
<div class="controls">
<strong>Password</strong><br/><input type="password" class="form-control custom-input-width" minlength="6" id="login-password" value="Asialouie!123" required>
</div>
<div class="control-group">
<div class="controls text-center">
<br/>
<input type="submit" class="btn btn-green" id="button-signup" value="Sign in">
<br/><p class="aligncenter"><br/>
Don't have an account? <a href="/register" >Sign up</a>
<br/>Forgot password? Reset
</p>
</div>
</form>
JQuery Ajax code:
$("#loginUserForm").submit(function(event) {
// Prevent the form from submitting via the browser.
event.preventDefault();
try{
const email = $("#login-email").val();
const password = $("#login-password").val();
console.log("email: "+email);
console.log("pass: "+password);
var data = {};
data.email =email;
data.message =password;
$.ajax({
url: '/users/loginUser',
type: 'POST',
data: JSON.stringify(data),
contentType: 'application/json',
/**
* A function to be called if the request succeeds.
*/
success: function(data, textStatus, jqXHR) {
window.location.assign("/profile/?id="+data._id);
},
error : function(error) {
//alert(error.name + ': ' + error.message);
console.log(error);
$(".alert-signin").show();
}
});
}
catch(err) {
console.log("err: "+err.message);
}
});
User Route Method:
router.post('/loginUser', function(req, res) {
console.log("in user login");
});
This route Post works:
router.post('/',function(req,res){
logger.info("email: "+req.body.email);
User.findOne({ email:req.body.email}, function (error, user) {
if(user){
console.log("user exists");
const error = new Error('User email account already exists.');
res.status(410);
res.send(JSON.stringify(error.message));
}
else{
//save user
var pwd = req.body.password;
bcrypt.genSalt(10, function(err, salt) {
if (err) {
logger.error("BCrype issue");
const error = new Error("Unable to register, please try again.");
//throw new Error('User email account already exists.');
res.status(420);
res.send(JSON.stringify(error.message));
} else {
//console.log('Salt: ' + salt);
bcrypt.hash(pwd, salt, function (err, hash) {
if (err) {
logger.error("ERROR! users bcrypt");
const error = new Error("Unable to register, please try again.");
res.status(420);
res.send(JSON.stringify(error.message));
} else {
var user = new User({
firstname:req.body.firstname,
lastname :req.body.lastname,
email :req.body.email,
password : hash,
public:1,
admin: false,
bio : "",
location : "",
avatar: "",
url: "",
activated:"n"
});
user.save(function (error, user) {
if (error){
res.send(error.message);
}
res.send(user)
});
}
});
}
});
}
});
});
I expect the route to take the login information and get into the LoginUser route and output "in user login"
Here is the console output when the login form is posted:
POST http://localhost:3000/users/loginUser 500 (Internal Server Error) jquery-3.4.1.min.js:2
I don't understand why it's showing jquery-3.4.1.min.js:2 in the console for the 500 error.
Any help would be greatly appreciated.
I think you should try the followings:
You should put method attribute in the form tag
If you have the following statement in your server code, remove it or comment it down.
app.use(bodyParser.json());
If you have any attributes in the script tag in which jQuery is written, then remove them.
What status code 500 is normally there is some error in the server-side code ( in the root ). Double-check the route code.
These all suggestions are what I did with my code when I faced the 500 error.
I started Node.js and general web few times ago and now I have a project where I have to develop a web server with an API in nodejs running on Express and I want to do it properly but I'm not sure if there's a the good way to do it.
It concerns about every post requests I'm sending to my API, here's an example :
Sign up :
I have a route app.get('/signup') and I'm sending a post request to my API to create new user. So with my guess I send a form with action = /signup method = "post" which means that on my server I've app.post('/signup'). In this post, I create a post request with all the information in my form and I send it to my API which creates the user and send back to the app.post('/signup') the answer. So basically, here the schema:
Get('/signup') -> Post('/signup') -> API('createUser') -> Post('signup')
Then I would like to go back to my app.get('/signup'), because I don't want to send html form the post one, and say "Hey it's ok" instead of showing the form so i'm doing a redirect but how could I know what to display in Get('/signup') ? Can I send a variable to know what to show to the user ? And btw, is it the proper way to do it ?
Thanks !
PS : it doesn't look very clear so here the code :
app.get('/signup', function(req, res) {
res.setHeader('Content-Type', 'text/html');
if (req.session.userId) { res.end("Connected as " + req.session.name); }
else {
res.end('<html><p>As a guest, you\'re signing up : </p><form action="/signup" method="post">' +
'First name: <input type="text" name="firstname"><br>' +
'Last name: <input type="text" name="lastname"><br>' +
'email: <input type="text" name="email"><br>' +
'password: <input type="text" name="password"><br>' +
'role: <input type="text" name="role"><br>' +
'<input type="submit" value="Submit">' +
'</form></html>');
}
});
app.post('/signup', function(req, res) {
request.post({
url: 'http://localhost:4242/signup',
form : {
firstname : req.body.firstname,
lastname : req.body.lastname,
email : req.body.email,
role : req.body.role,
password : req.body.password
}},
function (error, response, body) {
res.redirect('/signup');
});
});
Is it the good way to do it ?
Is there another way to send variable from post to get except the session variable ? (with the redirect) ?
I'm not sure I fully understand the question, but this is how I handle form submits with node.js.
Submit the form using jQuery/Ajax, so we can then get a response from the server after the POST.
$('#your-form').on('submit', function(e) {
e.preventDefault();
var formData = $(this).serializeArray();
$.ajax({
type: 'POST',
url: '/signup',
data: formData
}).success(function(response) {
if (response.success == '1') {
// Do something
} else {
// Do something - e.g. display an error message
}
});
});
Then on your Node.js server, you can handle the app.post('/signup') request, and once you're finished with your API calls, return a status message:
res.json({message: 'User created successfully.', success: '1'});
You can then use this JSON response to take the appropriate action.