How to handle response in react - node.js

I am new to react. Currently I am working on creating a login screen. I have this code:
function login(e) {
fetch('/login')
.then(response => {
if(response === 'fail'){
return(SignIn());
}else{
return(Ide());
}
})
.then((proposals) => {
console.log(proposals);
this.setState({ proposals });
});
}
export default function SignIn() {
const classes = useStyles();
return (
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<Avatar className={classes.avatar}>
</Avatar>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<form className={classes.form} noValidate>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="email"
label="Email Address"
name="email"
autoComplete="email"
autoFocus
/>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>
<Button
type="submit"
fullWidth
onClick={login}
variant="contained"
color="primary"
className={classes.submit}
>
Sign In
</Button>
</form>
</div>
</Container>
);
And then the login handler
app.get('/login', (req, res, next) => {
const { email, password } = req.body;
console.log(email, password);
//User.find({email: })
});
But when I press the submit button, email and password both console log as undefined. How do I send information using react between the client and the server? Thank you in advance

Whenever you use fetch as a way to send info to an endpoint like '/login' above, the req.body needs to be added as part of the fetch call. To do this, people usually do
fetch('/login', {
body: (whatever you send in the form of one object)
});
The body passed in as the second argument can be then used as req.body in your code that console.logs it.
This is not advised though since GET commands usually do not have bodies passed along as the second argument. Usually POST and PUT commands have the body to make it easy to add and change data. What I recommend is do:
fetch('/login/' + email + '/' + password);
This allows for an email and username object to be a part of your url in for your backend to use. This is one of the ways that people do GET commands without passing in a body. With the new format, you should change the backend to be:
app.get('/login/:email/:password', (req, res) => {
const email = req.params.email;
const password = req.params.password;
console.log(email, password);
With :email and :password in the url, this lets you use req.params and then directly call each identifier as the last value.
Btw if you feel like the fetch call above looks messy with the + commands, you can instead do:
fetch(`/login/${email}/${password}`);
Which are Template Literals that make it easier to read code by adding the values directly into the string. (Note they use the ` key next to the 1 key not ' or ")
Also if you want more info on fetch commands, I advise to start with the MDM Documentation. This website is extremely helpful whenever you need to learn something about JS or other web languages.

Related

Reset Password Page Not Rendering Correctly When Accessing from Reset Email Link

Ok, so first off, this is my first post. I've searched high and low for a solution, but have found none. I have posted this first on Udemy, for the course I've taken, but no one has answered, so I'm reposting it here.
I have been trying very hard to figure out why the new-password page will not display correctly for me. The reset link works fine, and I can even reset the password on my new password page when I am sent there from the email link.
However, no matter what I do, I can't get it to display any styling. It only gives me basic html. The logic works fine, it's just the page that doesn't display correctly.
I know it isn't a path issue to the css folder either. If I simply render as another basic page without any token logic, such as replacing my index page with the new-password page, then it displays normally. I just don't know what I'm missing, or if there was some updates that I need to take into consideration.
I'm hoping someone sees this and can help me out. It's the only thing that doesn't work right, and it's very frustrating.
Just to be a little more clear, if I do something like below, and just replace or create a route, the page shows up correctly. It's the token logic I believe that is breaking the rendering, I just don't know how, since I don't get any errors.
Please let me know what code you may need to see, as I'm not sure what sections would be helpful, there are a lot of moving parts here. I will be happy to post whatever is needed.
exports.getNewPassword = (req, res, next) => {
res.render("auth/new-password", {
path: "/new-password",
pageTitle: "Update Password",
});
};
With the logic built-in and following the email reset link, the below will not render any styling, only the html.
exports.getNewPassword = (req, res) => {
const token = req.params.token;
User.findOne({
resetToken: token,
resetTokenExpiration: { $gt: Date.now() },
})
.then((user) => {
if (!user) {
req.flash(
"error",
"That reset password link has already been used."
);
return res.redirect("/");
}
let message = req.flash("error");
message.length > 0 ? (message = message[0]) : (message = null);
res.render("auth/new-password", {
path: "/new-password",
pageTitle: "New Password",
errorMessage: message,
userId: user._id.toString(),
passwordToken: token,
});
})
.catch((err) => console.log(err));
};
I am using ejs for templating as well. As I said above, if I remove all token logic and just render the page as a normal view, it works fine.
<main>
<% if (errorMessage) { %>
<div class="user-message user-message--error"><%= errorMessage %></div>
<% } %>
<form class="login-form" action="/new-password" method="POST">
<div class="form-control">
<label for="password">Password</label>
<input type="password" name="password" id="password">
</div>
<input type="hidden" name="userId" value="<%= userId %>">
<input type="hidden" name="passwordToken" value="<%= passwordToken %>">
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
<button class="btn" type="submit">Update Password</button>
</form>
</main>
Well, in case anyone stumbles across this, the answer was pretty simple, though I'm not sure why in this one instance is was a problem. However, the solution was to add a forward slash in front of my path to the css location for the update password page.
Again, not sure why it needed it, seeing as all my other css and view pages were in the same folder structures and worked fine, but it apparently solved the issue. SMDH.
<link rel="stylesheet" href="/css/login.css" />

how make checkbox stay checked and reset in node js

I am working on a small project with checkbox and node js. I need the checked box stay on the screen after I click submit button and reset the form after clicking reset button.How can do that?
ejs code
<form method="post" action="/">
<input type="checkbox" name="preference" value="A">A
<input type="checkbox" name="preference" value="B">B
<input type="checkbox" name="preference" value="C">C
<input type="submit" value="Click to Submit">
<input type="reset" value="Erase and Restart">
</form>
node js
express.get('/', (req, res) => {
res.render('form');
});
express.post('/', (req, res) => {
console.log(req.body);
let checkedValue =req.body.preference;
let output = checkedValue==undefined?`You didn' make selection.`:`The preference iterm on menu is ${checkedValue}`;
res.render('form',{
output:output,
});
});
What's going on is that when you submit your form, the webpage is reloaded, so you lose your checked state. You can either save the values on your server and have them pre-checked using an optional checked flag in your ejs template or you can add some client side javascript to handle the form submission for you by writing and event handler for the submit event on the form.
if you expand your ejs template with a conditional checked value on your inputs, your returned page will have them pre-checked
<input type="checkbox" name="preference" <% if (submittedValue === "A") { %>checked<% } %> value="A">A
Or, here's a super simple bit of javascript that would send the values to your server
document.forms[0].addEventListener('submit', function (e) {
e.preventDefault(); // prevent the form from submitting with a page refresh
const data = { values: [] };
e.target.elements.forEach((formEl) => {
if (formEl.checked) data.values.push(formEl.value);
});
fetch('/urlToProcessYourForm', { method: 'POST', body: JSON.stringify(data) });
});

req.body value undefined for form field value set by javascript function

I am building a node.js,express.js and passport.js app. Once logged into the profile I ask the user to click a button “Get Location” to get the users location.
Profile.ejs
<form action="/testform" method="post" >
<div class="form-group">
<input type="text" class="form-control" id="latVal" placeholder="latitude">
<input type="text" class="form-control" id="longVal" placeholder="longitude">
</div>
<button type = "submit" class="btn btn-warning btn-sm">Save</button>
</form>
<button type = "submit" class="btn btn-warning btn-sm" onclick="getLocation()">Get Location</button>
onclick the getLocation() function is called which is located in mapCall.js
function getLocation()
…
//call to showLocation()
}
function showLocation(position) {
…
document.getElementById("latVal").value = latitude;
document.getElementById("longVal").value = longitude;
}
showLocation() sets the values in the form to the latitude (id="latVal") and longitude (id="longVal") returned from the API call. The values appear in the form field. From here I want to save these values to the users profile data in MongoDB which I try to achieve in routes.js by click of the “Save” button which triggers the function below
app.post('/testform', isLoggedIn, function(req, res) {
user.findById(req.user.id, function(err,user) {
if(!user) {
req.flash('error', 'No accound found');
return res.redirect('/profile');
}
user.location.latitude = req.body.latVal;
user.location.longitude = req.body.longVal;
user.save(function(err){
res.redirect('/profile');
});
});
});
When I console.log req.body.latVal and req.body.longVal the value for these variables is undefined. Nothing is saved in the db.
In server.js I have
var bodyParser = require('body-parser');
app.use(bodyParser());
Upon looking into proposed solutions to req.body returning undefined I tried
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
I didn’t think adding the two lines above would work because the value returned by the API is not in JSON format. This did not work. I checked the typeof for latitude and longitude and it is a number. I am not sure why req.body is not picking up the value.
My initial guess was that app.post tries to read the value before the API can return a value in which case req.body.latVal would read an empty field. I added the save button to test that theory which also proved wrong.
The closest thing I found to my issue is this which was never resolved.
Any guidance is highly appreciated or perhaps even a better way to accomplish this will be great. The reason I have the form fields populate is because I couldn't think of another way to send the values from the frontend to the backend for saving.
Add the name attribute to your inputs.
<input type="text" class="form-control" id="latVal" placeholder="latitude" name="latVal">
<input type="text" class="form-control" id="longVal" placeholder="longitude" name="longVal">
EDIT: (from the comment)
You can do an AJAX call to your server after the getLocation() call.
function getLocation() {
///you get the lat and long
showLocation(position)
saveLocation(latitude, longitude)
.then(function(resp){
//do something with resp
})
}
function saveLocation(latitude, longitude) {
//we have native fetch in newer browsers, so
return fetch("/testform", {
method: "POST",
headers: {
"Content-Type": "application/json; charset=utf-8", //if this doesn't work use the below one
// "Content-Type": "application/x-www-form-urlencoded",
},
body: JSON.stringify({latitude,longitude}), // body data type must match "Content-Type" header
})
.then(response => response.json());
}
This is just an outline of what you can do. Extend this code to your needs.
You are correct in most parts ,You just have to replace ID with name.that is the only way nodejs will be able to locate to your input field

Getting "Cannot POST" with registration page using Sequelize

I'm sure there's a sound reason as to why I can't get this to work but I've been staring at the code for a long time and I'm brutally stuck. I'm trying to build out a very basic registration form that should store the data in my PostgreSQL database. I'm using bcrypt to hash out the password, but even without still having issues.
My HTML has the following:
<form action="/register/new" method="post">
<label for="username">Username</label>
<input type="text" name="username">
<label for="password">Password</label>
<input type="password" name="password">
<label for="confirm">Confirm Password</label>
<input type="password" name="confirm">
<button type="submit">Submit</button>
</form>
Then for the code I have:
app.get("/register", function(req,res){
res.render("register");
})
app.post('register', function(req,res){
let newUser = {
username: req.body.username,
passwordHash: bcrypt.hashSynce(req.body.password, 8)
}
models.Users.create(newUser).then(function(){
res.redirect('/login');
})
});
The plan for the registration data to be stored and the user redirected to the login page, login stores them in session, and so on. I thought for a bit that the issue was the action on the form but regardless I'm getting Cannot POST /register/new. I've also played around with doing a findOrCreate and do a comparison but I wanted to start with actually just creating before I make it more complex. The same issue occurs with cannot post.
Any thoughts on what I need to change?
Probably would've worked better if I did a app.post("/register"...
Simple miss of an "/"
try this modified code...
app.post('/register', function(req,res) {
let newUser = {
username: req.body.username,
passwordHash: bcrypt.hashSync(req.body.password, 8)
}
// if it does not connect/save try using models.User instead of models.Users below.
models.Users.create(newUser).then(function(){
res.location('/login');
res.redirect('/login');
})
});

Response with express and nodejs application

I have an express server and a login page developed in HTML(with jquery). after login button is hit, jQuery fires a HTTP get request to express server and after user gets verified, user should be redirected to landing page with some data like name, gender, age etc(that is fetched from mongoDB on server itself). When I do res.sendFile or res.redirect, The parameters (name, age, gender) could not be sent on the view which is required there in response.
Jquery:
$("#submit").click(function() {
user = $("#email").val();
pass = $("#password").val();
$.post("https://localhost:443/login", {
user: user,
password: pass
}, function(response) {
if (response) {
alert("login success" + response.userName);
}
});
});
HTML:
<form id="grad">
<h1 style="margin-top: -10px; text-shadow: 1px 1px whitesmoke;">Login</h1>
<h3 style="padding-bottom: 30px;font-size: 22px ">Please enter email ID and password.</h3>
<div class="group">
<input type="email" id="email" name="email"><span class="highlight"></span><span class="bar"></span>
<label>Email ID</label>
</div>
<div class="group">
<input type="password" id="password" name="password"><span class="highlight"></span><span class="bar"></span>
<label>Password</label>
</div>
<div class="group">
<input type="submit" id="submit" class="button buttonRed" value="Login" onclick="validateUser()" />
<input type="reset" class="button buttonRed" value="Reset" />
</div>
</form>
Express:
app.post('/login', function (req, res) {
// some logic to validate user and fetch details, which will be used on view.
res.sendFile('landing**strong text**page.html', { root: "public" } );
})
The post route should save the user in session before returning the response to jQuery code. Essentially the response from post route should be only success or response.
There should also be a get route to redirect the user to home page (or the page where u want the user after login).
This get route will first check if there is a user in session then redirect accordingly.
Use express-session to save the session in app.
Simple solution for starter. This is NOT a practical solution in production site, just for starter who wants to learn the basic.
Jquery
$("#submit").click(function() {
user = $("#email").val();
pass = $("#password").val();
$.post("https://localhost:443/login", {
user: user,
password: pass
}, function(response) {
$('body').append(response); //append html to body returned from /login
});
});
Express Server:
app.post('/login', function (req, res) {
// some logic to validate user and fetch details, which will be used on view.
var userInfo = validateAndFetchDetailFunc();
res.send('Username: ' + userInfo.name + '<br>Gender: ' + userInfo.gender);
})
The real solution should be using session to management the login session for user.
User login with username/password
Create a session at the server side, send back a session key or access token to the client.
When the client request user information, use the session key or access token to retrieve the user info
Render the html page with the user info from the saved session
For express server, you can start to learn session with express-session.

Resources