Page is rendering the users after second submit - node.js

currently learning React and want to POST-Data to my Database and after the Post the table with all users should update automatically.
Do you have any suggestion why it is not working?
I try to use the useEffect and add also the allData array, but it is then in an infinite loop.
So currently it is just loading the page if I again press the submit button.
import React from "react";
import { useState, useEffect } from "react";
import axios from "axios";
const Form = () => {
const [Username, setUsername] = useState("");
const [Password, setPassword] = useState("");
const [userList, setUserList] = useState([]);
const allData = () => {
axios.get("http://localhost:3001/api/alluser").then((response) => {
console.log(response.data);
setUserList(response.data);
});
};
useEffect(() => {
allData();
}, []);
const postdata = () => {
axios.post("http://localhost:3001/api", {
Username: Username,
Password: Password,
});
allData();
};
const deletedata = (e) => {
const users_id = e.target.id;
axios.post("http://localhost:3001/api", {
users_id: users_id,
});
};
const clickHandler = (e) => {
deletedata(e);
};
return (
<>
<label name="Username">
<input
onChange={(e) => setUsername(e.target.value)}
type="text"
name="Username"
placeholder="Username"
/>
</label>
<label name="password">
<input
onChange={(e) => setPassword(e.target.value)}
type="text"
name="Password"
placeholder="Password"
/>
</label>
<button onClick={postdata}>Submit</button>
{userList.map((val) => {
return (
<>
<li key={val.users_id}>
{val.users_id}
<button onClick={clickHandler}>
Löschen
</button>
</li>
</>
);
})}
</>
);
};
export default Form;

allData() should wait until axios.post returns the response. You could use callbacks or async/await to achieve it.
const postdata = async () => {
await axios.post("http://localhost:3001/api", {
Username: Username,
Password: Password,
});
allData();
};
or
const postdata = () => {
axios.post("http://localhost:3001/api", {
Username: Username,
Password: Password,
}).then(() => { allData(); });
};

Related

axios.get not working while am i searching product name

backend
const ProductListFilter = async (req, res) => {
try {
const productList = await productModel.find(req.query).collation({ locale: "en", strength: 2 });
return res
.status(201)
.send({
status: true,
message: `Total ${productList.length} product found `,
data: productList,
});
} catch (error) {
res.status(500).send({ status: false, message: error.message });
}
};
frontend
import axios from "axios";
import { useState } from "react";
const ProductListFilter = () => {
const [search, setSearch] = useState();
const handleChange = (e) => {
setSearch({ ...search, [e.target.name]: e.target.value });
};
const handleSubmit = async (e) => {
e.preventDefault();
await axios
.get(`http://localhost:5000/ProductListFilter`)
.then((res) => alert(res.data.message))
.catch((err) => console.log(err.response.data.message));
};
console.log(search);
return (
<div>
<form onSubmit={handleSubmit}>
<label htmlFor="search">
<input type="search" name="search" id="search" onChange={handleChange} />
<button type="submit">Submit</button>
</label>
</form>
</div>
);
};
export default ProductListFilter;
you need to add name in query param as shown below.
import axios from "axios";
import { useState } from "react";
const ProductListFilter = () => {
const [search, setSearch] = useState();
const handleChange = (e) => {
setSearch({ ...search, [e.target.name]: e.target.value });
};
const handleSubmit = async (e) => {
e.preventDefault();
await axios
.get(`http://localhost:5000/ProductListFilter?name=${search.name}`)
.then((res) => alert(res.data.message))
.catch((err) => console.log(err.response.data.message));
};
console.log(search);
return (
<div>
<form onSubmit={handleSubmit}>
<label htmlFor="search">
<input type="search" name="search" id="search" onChange={handleChange} />
<button type="submit">Submit</button>
</label>
</form>
</div>
);
};
export default ProductListFilter;

Redirects to wrong page when logging in

it redirects to an empty js file when logging in, not to the js file I wrote. Should I redirect in my database code?
////////////////
const client = require('../../db')
const express = require('express');
const app = express();
const cors = require("cors");
app.use(cors());
app.use(express.json()); //req.body
app.listen(2136, ()=>{
console.log("Sever is now listening at port 5000");
})
client.connect();
app.post("/login", async (req, res) => {
try {
const { email, password } = req.body;
const user = await client.query(
`SELECT * FROM users WHERE email=$1 AND password=$2`,
[email, password]
);
if (user.rows.length === 0) {
res.status(404).send("Kullanıcı adı veya şifre yanlış");
} else {
res.send("Kullanıcı adı veya şifre doğru");
}
}catch (err) {
response
.status(500)
.json({ message: "Error in invocation of API: /login" })
}
});
this is my database code.
///////////////////////
import {
BrowserRouter as Router,
Route
} from "react-router-dom";
import React, { useState } from 'react'
import Navbar from '../../common/Navbar/Navbar';
import AdminPage from './AdminPage';
const User = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [user, setUser] = useState([]);
const [error, setError] = useState('');
const onSubmitForm = async e => {
e.preventDefault();
try {
const response = await fetch(`http://localhost:2136/login`,{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password }),
});
console.log(email,password)
console.log(response);
if ((response.status)===404) {
setError('Invalid email or password');
} else
{
window.location.replace(`/AdminPage`);
}
} catch (err) {
console.error(error);
setError('An error occurred. Please try again later.');
}
};
return (
<>
<Navbar/>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.4.1/dist/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"></link>
<div className="container text-center">
<h1 className="my-5">Search for the Dormitory You Want</h1>
<form className="d-flex" onSubmit={onSubmitForm}>
<input
type="text"
name="name"
placeholder="Enter email ..."
className="form-control"
value={email}
onChange={e => setEmail(e.target.value)}
/>
<input
type="text"
name="name"
placeholder="Enter password ..."
className="form-control"
value={password}
onChange={e => setPassword(e.target.value)}
/>
<button className="btn btn-success">Submit
</button>
</form>
</div>
</>
)
}
export default User
this is my login page. the page it redirects to is a blank page. i don't understand why.
///////////////
import React, { useState } from 'react'
import AdminNavbar from '../../common/Navbar/AdminNavbar';
const AdminPage = () => {
return (
<>
<AdminNavbar/>
</>
);
}
export default AdminPage
and this the page I want to redirect AdminPage.So what can i do?
///////////////////
The difference between assign() and replace():
replace() removes the current URL from the document history.
With replace() it is not possible to use "back" to navigate back to the original document.
You can use assign method instead of location method

How to GET data from mongoDB ATLAS and display in React App

I am new to MERN stack and been working on a project that uses different driver information entered from the user and display that information back to the user in a table. I have successfully connected to MongoDB Atlas and also can enter data using my front end but I can't seem to figure out how to retrieve the data back to the front end. Can y'all help me fetch the data back and how I can present it in a tabular format.
Thanks in advance.
//driver model
onst mongoose = require('mongoose');
const DriverSchema = new mongoose.Schema({
name:{type: String, required:true},
email:{type: String, required:true},
phone:{type: Number, required:true},
address:{type:String, required:true},
country:{type: String, required:true}
});
const DriverModel = mongoose.model("drivers", DriverSchema)
module.exports = DriverModel;
//routes
const router= require('express').Router();
let Driver = require('../models/driver');
router.route('/getDrivers').get((req, res) =>{
Driver.find()
.then(drivers => res.json(drivers))
.catch(err => res.status(400).json('Error: '+ err));
}
)
router.route('/createDrivers').post((req, res) => {
const name = req.body.name;
const email = req.body.email;
const phone = req.body.phone;
const address = req.body.address;
const country =req.body.country;
const newDriver = new Driver({name, email, phone, address, country});
newDriver.save()
.then(() => res.json('Driver added!'))
.catch(err => res.status(400).json('Error: ' + err));
});
router.route('/:id').get((req,res)=> {
Driver.findById(req.params.id)
.then(drivers => res.json(drivers))
.catch(err => res.status(400).json('Error: ' + err));
})
router.route('/:id').delete((req, res) => {
Driver.findByIdAndDelete(req.params.id)
.then(() => res.json('Driver deleted.'))
.catch(err => res.status(400).json('Error: ' + err));
});
router.route('/update/:id').post((req, res) => {
Driver.findById(req.params.id)
.then(driver => {
driver.name = req.body.name;
driver.email = req.body.email;
driver.phone = req.body.phone;
driver.address = req.body.address;
driver.country =req.body.country;
driver.save()
.then(() => res.json('Driver updated!'))
.catch(err => res.status(400).json('Error: ' + err));
})
.catch(err => res.status(400).json('Error: ' + err));
});
module.exports = router;
//frontend
import React from 'react';
import Sidebar from '../../components/sidebar/Sidebar';
import Navbar from '../../components/navbar/Navbar';
import { useEffect, useState } from 'react';
import "./dbtrial.scss" ;
import Axios from "axios";
function Dbtrial() {
const [listOfDrivers, setListOfDrivers]= useState([]);
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [phone, setPhone] = useState(0);
const [address, setAddress] = useState("");
const [country, setCountry] = useState("");
useEffect(() => {
const fetchDrivers= async () =>{
try{
const response = await fetch("http://localhost:3001/driver/getDrivers")
if(!response.ok) throw Error('Did not recieve expected data');
const listDrivers = await response.json();
console.log(listDrivers);
setListOfDrivers(listDrivers);
setFetchError(null);
} catch(err){
setFetchError(err.message)
}
}
setTimeout(() => {
(async () => await fetchDrivers())();
}, 2000)
//(async () => await fetchDrivers())();
}, [])
const createDrivers = () =>{
Axios.post("http://localhost:3001/createDrivers", {
name,
email,
phone,
address,
country,
}).then((response) =>{
setListOfDrivers([...listOfDrivers,
{
name, email, phone, address,
country,
},
]);
//alert("Driver added!");
});
}
return (
<div className="db">
<Sidebar />
<div className="dbq">
<Navbar />
<div className="formInput">
<label>Name</label>
<input type="text" placeholder="name" onChange={(event) => {
setName(event.target.value);
}} />
</div>
<div className="formInput">
<label>Email</label>
<input type="email" placeholder="email" onChange={(event)=> {setEmail(event.target.value);}}/>
</div>
<div className="formInput">
<label>Phonenumber</label>
<input type="text" placeholder="0923668881 " onChange={(event) => {setPhone(event.target.value);}}/>
</div>
<div className="formInput">
<label>Address</label>
<input type="text" placeholder="Addis Ababa" onChange={(event)=> {setAddress(event.target.value);}}/>
</div>
<div className="formInput">
<label>Country</label>
<input type="text" placeholder="country" onChange={(event) => {setCountry(event.target.value);}}/>
<button type="submit" onClick={createDrivers}>Send</button>
</div>
</div>
</div>
)
}
export default Dbtrial
On your backend, your router functions don't seem to use
res.send
Where you are doing res.json, you can do something like
res.status(200).send(responseData)
So in router.routes.findById' then callback, instead of:
.then(drivers =>
res.json(drivers))
You can have
.then(drivers =>
res.status(200).send(JSON.stringify(drivers)) //maybe you don't need to use JSON.stringify here
In your frontend, I'm not sure what response.data will be defined after your api call. To be sure what properties the response has, you can console.dir(response.data), console.dir(response.json()) and check the result in the browser console. (Not too familiar with axios) If the result is your driver array, you can do like are already doing with setDriverList to set the state, but probably with the result of, or a part of the result of response.data or response.data.devices or something like that.
So I would do something like
//...api call
.then((response) => {
if(response.status === 200){
setDriverList(response.data.drivers) //or response.data or whatever
}
})

Error Cannot read property '_id' of null?

It's been all day I tried to update a user profile but I keep getting an error Cannot read property _id null. I can't figure out whats the problem is. I've checked many times backend and frontend, Even checking other's Github repository but I cannot figure out where is the problem. Please help me out with this. Here is my code
And please is there any better way to fetch the user if I don't fetch from userInfo please tell me
if you want to check the full repository here is the GitHub link
Here is what I see in the console (
PUT /api/users/profile 500 62.771 ms - 642
Profile.js
import { useEffect, useState } from 'react';
import { Button, Col, Container, Form, InputGroup, Row } from 'react-bootstrap';
import { toast, ToastContainer } from 'react-toastify';
import { useDispatch, useSelector } from 'react-redux';
import { updateUserProfile } from '../actions/userActions';
// import { USER_UPDATE_PROFILE_RESET } from '../constant/userConstants';
const Profile = ({ history }) => {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [pic, setPic] = useState();
const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const [picMessage, setPicMessage] = useState();
const [passwordType, setPasswordType] = useState('password');
const [passwordType2, setPasswordType2] = useState('password');
const [showPass, setShowPass] = useState(false);
const [showPass2, setShowPass2] = useState(false);
const dispatch = useDispatch();
// const userDetails = useSelector((state) => state.userDetails);
// const { user } = userDetails;
// console.log(` this is from line 25 ${user}`);
const userLogin = useSelector((state) => state.userLogin);
const { userInfo } = userLogin;
const userUpdateProfile = useSelector((state) => state.userUpdateProfile);
const { success } = userUpdateProfile;
useEffect(() => {
if (!userInfo) {
history.push('/login');
} else {
setName(userInfo.name);
setEmail(userInfo.email);
setPic(userInfo.pic);
}
if (success) {
return toast.success('Updated Successfully');
}
showPass ? setPasswordType('text') : setPasswordType('password');
showPass2 ? setPasswordType2('text') : setPasswordType2('password');
}, [showPass, showPass2, dispatch, history, userInfo, success]);
const postDetails = (pics) => {
setPicMessage(null);
if (pics.type === 'image/jpeg' || pics.type === 'image/png') {
const data = new FormData();
data.append('file', pics);
data.append('upload_preset', 'codeblogger_profile_image');
data.append('cloud_name', 'dhuej17x0');
fetch('https://api.cloudinary.com/v1_1/dhuej17x0/image/upload', {
method: 'post',
body: data,
})
.then((res) => res.json())
.then((data) => {
setPic(data.secure_url.toString());
})
.catch((err) => {
toast.error(err);
});
} else {
setPicMessage('Please Select an Image');
toast.error(picMessage);
}
};
const submitHandler = (e) => {
e.preventDefault();
dispatch(updateUserProfile({ name, email, password, pic }));
};
return (
<div className="profilePage mt-4 py-3">
<ToastContainer />
<Container>
<h2>PROFILE</h2>
<Row className="profileContainer">
<Col md={6}>
<Form onSubmit={submitHandler}>
<Form.Group controlId="name" className="mb-2">
<Form.Label>Name</Form.Label>
<Form.Control
type="name"
value={name}
placeholder="Enter Name"
onChange={(e) => setName(e.target.value)}
/>
</Form.Group>
<Form.Group controlId="email" className="mb-2">
<Form.Label>Email</Form.Label>
<Form.Control
type="email"
value={email}
placeholder="Enter email"
onChange={(e) => setEmail(e.target.value)}
/>
</Form.Group>
<Form.Group controlId="password" className="mb-2">
<Form.Label>New Password</Form.Label>
<InputGroup>
<Form.Control
type={passwordType}
placeholder="New Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<InputGroup.Text>
<i
onClick={() => setShowPass(!showPass)}
className={showPass ? 'fas fa-eye-slash' : 'fas fa-eye'}
style={{ cursor: 'pointer' }}></i>
</InputGroup.Text>
</InputGroup>
</Form.Group>
<Form.Group controlId="confirmPassword" className="mb-2">
<Form.Label>Confirm Password</Form.Label>
<InputGroup>
<Form.Control
type={passwordType2}
placeholder="Confirm Password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
/>
<InputGroup.Text>
<i
onClick={() => setShowPass2(!showPass2)}
className={showPass2 ? 'fas fa-eye-slash' : 'fas fa-eye'}
style={{ cursor: 'pointer' }}></i>
</InputGroup.Text>
</InputGroup>
</Form.Group>
<Form.Group controlId="pic" className="mb-2">
<Form.Label>Change Profile Picture</Form.Label>
<Form.File
onChange={(e) => postDetails(e.target.files[0])}
id="custom-file"
type="image/png"
custom
/>
</Form.Group>
<Button
type="submit"
variant="success"
style={{ letterSpacing: '2px' }}>
UPDATE
</Button>
</Form>
</Col>
<Col
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}>
<img src={pic} alt={name} className="profilePic" />
</Col>
</Row>
</Container>
</div>
);
};
export default Profile;
Here is userAction.js file
// User Details Action Start===========================================================================
export const getUserDetails = (id) => async (dispatch, getState) => {
try {
dispatch({
type: USER_DETAILS_REQUEST,
});
const {
userLogin: { userInfo },
} = getState();
const config = {
headers: {
Authorization: `Bearer ${userInfo.token}`,
},
};
const { data } = await axios.get(`/api/users/${id}`, config);
dispatch({
type: USER_DETAILS_SUCCESS,
payload: data,
});
} catch (error) {
const message =
error.response && error.response.data.message
? error.response.data.message
: error.message;
if (message === 'Not authorized, token failed') {
dispatch(logout());
}
dispatch({
type: USER_DETAILS_FAIL,
payload: toast.error(message),
});
}
};
// User Details Action Complete===========================================================================
// User Profile Details Action Start===========================================================================
export const updateUserProfile = (user) => async (dispatch, getState) => {
try {
dispatch({
type: USER_UPDATE_PROFILE_REQUEST,
});
const {
userLogin: { userInfo },
} = getState();
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${userInfo.token}`,
},
};
const { data } = await axios.put(`/api/users/profile`, user, config);
dispatch({
type: USER_UPDATE_PROFILE_SUCCESS,
payload: data,
});
dispatch({
type: USER_LOGIN_SUCCESS,
payload: data,
});
localStorage.setItem('userInfo', JSON.stringify(data));
} catch (error) {
const message =
error.response && error.response.data.message
? error.response.data.message
: error.message;
if (message === 'Not authorized, token failed') {
dispatch(logout());
}
dispatch({
type: USER_UPDATE_PROFILE_FAIL,
payload: toast.error(message),
});
}
};
// User Profile Details Action Complete===========================================================================
Backend Usercontroller.js file
export const updateUserProfile = asyncHandler(async (req, res) => {
const user = await User.findById(req.user._id);
if (user) {
user.name = req.body.name || user.name;
user.email = req.body.email || user.email;
user.pic = req.body.pic || user.pic;
if (req.body.password) {
user.password = req.body.password;
}
const updatedUser = await user.save();
res.json({
_id: updatedUser._id,
name: updatedUser.name,
email: updatedUser.email,
pic: updateUser.pic,
isAdmin: updatedUser.isAdmin,
token: generateToken(updatedUser._id),
});
} else {
res.status(404);
throw new Error('User not found');
}
});
routes.js file
import express from 'express';
import {
adminUpdateUserProfile,
deleteUser,
getUserById,
getUserProfile,
getUsers,
loginUser,
registerUser,
updateUserProfile,
} from '../controller/userController.js';
import { admin, protect } from '../middleware/authMiddleware.js';
const router = express.Router();
router.route('/').post(registerUser).get(protect, admin, getUsers);
router.route('/login').post(loginUser);
router
.route('/profile')
.get(protect, getUserProfile)
.put(protect, updateUserProfile);
router
.route('/:id')
.delete(protect, admin, deleteUser)
.get(protect, admin, getUserById)
.put(protect, admin, adminUpdateUserProfile);
export default router;

Password hashing not working on Put request

Using bcryptjs library and got 2 issues when performing Put request:
1- On insomnia / postman, server returns hashed password, but it returns "unhashed" on client side inspect console tools.
2- I can not perform a login with new password credential.
Any visible syntax mistake on server code or quick suggestions please? Tks!
CLIENT SIDE CODE:
function DevUpdateForm() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [techs, setTechs] = useState("");
async function updateUser(e) {
e.preventDefault()
const dataUpdate = { name, email, password, techs}
const response = await api.put(`/devs/${dev._id}`, dataUpdate);
console.log(response);
setName('');
setEmail('');
setPassword('');
setTechs([]);
}
return (
<div className="update-profile">
<strong>Alterar</strong>
<img src={dev.avatar_url} alt={dev.name}/>
<form onSubmit={updateUser} >
<div className="input-block">
<label htmlFor="name">Nome:</label>
<input
name="name"
id="name"
type="text"
placeholder={"Alterar nome"}
value={name}
onChange={e => setName(e.target.value)}
/>
</div>
<div className="input-block">
<label htmlFor="email">E-mail:</label>
<input
name="email"
id="email"
type="text"
placeholder={"Alterar email"}
value={email}
onChange={e => setEmail(e.target.value)}
/>
</div>
<div className="input-block">
<label htmlFor="password">Senha:</label>
<input
name="password"
id="password"
type="password"
placeholder={"Digite nova senha"}
value={password}
onChange={e => setPassword(e.target.value)}
/>
</div>
<div className="input-block">
<label htmlFor="techs">Techs:</label>
<input
name="techs"
id="techs"
type="text"
placeholder={"Alterar tecnologias"}
value={techs}
onChange={e => setTechs(e.target.value)}
/>
</div>
<button type="submit" >Salvar</button>
</form>
</div>
)
}
export default DevUpdateForm;
SERVER SIDE UPDATE CONTROLLER:
async update(req, res, next) {
try {
const { name, email, password, techs } = req.body;
const { _id } = req.params;
const techsArray = parseStringAsArray(techs);
let dev = await Dev.findByIdAndUpdate(_id, {
name,
email,
password,
techs: techsArray
},
{new: true});
dev = await Dev.findById(_id)
dev.password = await bcrypt.hash(dev.password, 8)
if (dev !== null) {
res.status(200).send({
data: dev,
message: "Dev has been updated!"
});
} else {
res.status(404).end();
}
} catch (error) {
next(error)
}
},
ROUTE:
routes.put('/devs/:_id', DevController.allowIfLoggedin, DevController.grantAccess('updateAny', 'profile'), DevController.update);
After finding the model and set new values to user model. you have to execute .save() statement to update existing changes.
async update(req, res, next) {
try {
const { name, email, password, techs } = req.body;
const { _id } = req.params;
const techsArray = parseStringAsArray(techs);
let dev = await Dev.findByIdAndUpdate(_id, {
name,
email,
password,
techs: techsArray
},
{new: true});
dev = await Dev.findById(_id)
dev.password = await bcrypt.hash(dev.password, 8)
dev.save();// add this to save new password
if (dev !== null) {
res.status(200).send({
data: dev,
message: "Dev has been updated!"
});
} else {
res.status(404).end();
}
} catch (error) {
next(error)
}
},

Resources