I am new to React Native. I created a Registration App connected to a local PostgreSql Database. I am using Formik for the form, after submitting the form it is recorded in the database. The app refreshes everytime I save the code. However after some refreshes, the data is duplicated in the database. I am using axios and a Rest API. Also using nodemon for the server.
Duplicated Data in the Database
POST REQUEST
const url = 'http://192.168.254.106:5000/users';
handleMessage(null);
handleMessage('Successfully Signed Up!', 'SUCCESS');
try {
const response = await axios.post(url, credentials);
} catch (error) {
handleMessage('An Error Occured.');
}
setSubmitting(false);
}, []);
REST API
const app = express();
const cors = require('cors');
const pool = require('./database');
//middleware
app.use(cors());
app.use(express.json());
//ROUTES
//create user
app.post('/users', async (req, res) => {
try {
const { fullname, email, birthdate, password } = req.body;
const user = await pool.query(
'INSERT INTO users(fullname, email, birthdate, password) VALUES($1, $2, $3, $4) RETURNING *',
[fullname, email, birthdate, password],
);
} catch (err) {
console.error(err.message);
}
});
//get all users
app.get('/users', async (req, res) => {
try {
const allUsers = await pool.query('SELECT * FROM users');
res.json(allUsers.rows);
} catch (err) {
console.error(err.message);
}
});
//get a user
app.get('/users/:id', async (req, res) => {
try {
const { id } = req.params;
const user = await pool.query('SELECT * FROM users WHERE user_id=$1', [id]);
res.json(user.rows);
} catch (err) {
console.error(err.message);
}
});
//update a user
app.put('/users/:id', async (req, res) => {
try {
const { id } = req.params;
const { email } = req.body;
const updateUser = await pool.query('UPDATE users SET email = $1 WHERE user_id=$2', [email, id]);
res.json('Updated!');
} catch (err) {
console.error(err.message);
}
});
//delete a user
app.delete('/users/:id', async (req, res) => {
try {
const { id } = req.params;
const deleteUser = await pool.query('DELETE FROM users WHERE user_id=$1', [id]);
res.json('Deleted!');
} catch (err) {
console.error(err.message);
}
});
app.listen(5000, () => {
console.log('Server is up');
});
Related
I have created a login page and a about page the user will only access the about page if the user is logged in.
I am trying to authenticate the user by using the tokens generated while signing in, but the token is not getting authenticated even after signing in with the correct credentials. I don't know what is the problem?
This is code to my sign-in and token generating method
const express = require("express");
const { default: mongoose } = require("mongoose");
const router = express.Router();
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");
require("../db/conn");
const User = require("../model/userSchema");
const cookieParser = require('cookie-parser');
const Authenticate = require("../middleware/authenticate");
router.use(cookieParser());
//LOgin route
router.post("/signin", (req, res)=>{
if(!req.body.email || !req.body.password){
return res.status(400).json({error: "Plz fill the required data"});
}else{
bcrypt.hash(req.body.password, 12, function (err, hash) {
User.findOne({email: req.body.email}, function (err, foundUser) {
if(err){
console.log(err);
}else{
if(foundUser){
bcrypt.compare(req.body.password, foundUser.password, function (err, result) {
if(result){
return res.json({message: "successfully log in"})
}else{
return res.json({message: "incorrect password"});
}
});
const email = req.body.email;
const token = jwt.sign(
{ user_id: foundUser._id, email },
process.env.TOKEN_KEY,
{
expiresIn: "720h",
}
);
foundUser.tokens = foundUser.tokens.concat({token: token});
foundUser.save();
// res.status(200).json(foundUser);
console.log(foundUser);
}else{
return res.status(400).json({message: "user not found"});
};
}
})
})
}
});
//about us page
router.get("/about", Authenticate, function (req, res) {
console.log("about running");
res.send(req.rootUser);
});
module.exports = router;
this is the code to authenticate the user
require("dotenv").config({path: "./config.env"});
const jwt = require("jsonwebtoken");
const User = require("../model/userSchema");
const Authenticate = async(req, res, next) =>{
try {
const token = req.cookies.jwtoken;
const verifyToken = jwt.verify(token, process.env.TOKEN_KEY);
const rootUser = await User.findOne({ _id: verifyToken._id, "tokens.token": token});
if(!rootUser) {
throw new Error("User not found")
}
req.token = token;
req.rootUser = rootUser;
req.userID = rootUser._id;
next();
} catch (err) {
console.log(err);
return res.status(401).send("Unauthorized: No token provided");
}
}
module.exports = Authenticate;
This is react based code of: About-page to display it or not based on user's authenticity.
const navigate = useNavigate();
const callAboutPage = async() =>{
try {
const res = await fetch("/about",{
method: "GET",
headers: {
Accept: "application/json",
"Content-Type" : "application/json"
},
credentials: "include"
});
const data = await res.json();
console.log(data);
if(!res.status === 200){
const error = new Error(res.error);
throw error;
}
} catch (err) {
console.log(err);
navigate("/login");
}
}
As said in the comment looks like there is a issue on the process for setting up the jwtoken, and when you sign in, you just need to find the user and compare the password, there is no need to do the hash with Bcrypt, since you're not registing new user, for example, i will use Async/await instead of callback function, in order for you to read it much more easier:
//Login route
router.post("/signin", async (req, res)=> {
const { reqEmail, reqPassword } = req.body; //destructuring so less thing to write at the next step
if(!reqEmail || !reqPassword) {
return res.status(400).json({message: "Plz fill the required data"});
}
try {
const foundUser = await User.findOne({email: reqEmail})
if(!foundUser) {
return res.status(400).json({message: "Wrong username or password!"})
}
const result = await bcrypt.compare(reqPassword, foundUser.password);
if(!result){
return res.json({message: "Wrong username or password!"})
} else {
const accessToken = jwt.sign(
{ user_id: foundUser._id, email: foundUser.email},
process.env.TOKEN_KEY,
{ expiresIn: "720h",}
);
// I am confuse what are you trying to do here, in your place I would set up on the cookie since you do that on your authentification.
res.cookie("jwt", accessToken, {
maxAge: 60000, // 60 sec for testing
httpOnly: true,
sameSite: false, //false only for dev
secure: false, //false only for dev
})
res.status(200).json(foundUser);
};
} catch (error) {
return res.status(500).json({message: `${error}`})
}
Than the authentification middleware :
// ...
const Authenticate = (req, res, next) => {
const accessToken = req.cookies.jwt
if(!accessToken) {
return res.status(401).json({error: "Unauthorized: No token provided"});
}
try {
const user = jwt.verify(accessToken, process.env.TOKEN_KEY)
if(user) {
req.user = user
return next();
}
} catch (error) {
return res.status(403).json({error: "Forbidden token error"})
}
}
about page component it's simple for now since you don't manage any state
const navigate = useNavigate();
const callAboutPage = async() =>{
try {
const res = await fetch("/about",{
headers: {
"Content-Type": "application/json"
},
credentials: "include"
});
if(res.status === 200){
const data = await res.json();
// set up the state for rendering
console.log(data);
} else {
// you can also create a state to catch the error message from the backend, in this case the response json should be move to above the if statement.
throw new Error("You must log in to get access")
// than you can display this error message, or from the backend using state for this bloc, and the catch bloc
// navigate to /login
}
} catch (err) {
console.log(err);
navigate("/login");
}
}
router.use(cookieParser());
Try to use cookieParser with app.use instead. (app from express instense)
Expample:
const app = express();
app.use(cookieParser());
and try to put it before server listening in index.js or app.js file.
Hope it help.
I can't connect to MongoDB database, yet I tried everything ! I have successfully replaced the password.
const mongoose = require("mongoose");
mongoose
.connect(
"mongodb+srv://vibess:0KksWIBp6slcBLm0#cluster0.iuvoi.mongodb.net/?retryWrites=true&w=majority",
{
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
}
)
.then(() => console.log("Connected !!"))
.catch(() => console.log("Not connected!"));
Here is the Database
MangoDB
You will need another function to complete the operation. the function is usually called run then you need to write all the operations of your server in the scope of this function. here is an example of a server of mine Also you need to declare the name of your database before text retrywrites=true
//connect to mongodb
const uri = `mongodb+srv://${process.env.DB_USER}:${process.env.DB_PASS}#cluster0.qtoag.mongodb.net/Teletale?retryWrites=true&w=majority`;
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
async function run() {
try {
await client.connect((err) => {
const db = client.db("Teletale");
const djiPackages = db.collection("Devices");
const bookingsCollection = db.collection("bookings");
const testimonialCollection = db.collection("testimonials");
const usersCollection = db.collection("users");
// ==============GET API ====================
//GET API
app.get("/", (req, res) => {
res.send("Welcome to Teletale");
});
//GET API (dji Package)
app.get("/Devices", async (req, res) => {
const result = await djiPackages.find({}).toArray();
res.send(result);
});
//GET API (users)
app.get("/users", async (req, res) => {
const result = await usersCollection.find({}).toArray();
res.send(result);
});
// verify admin data form database
app.get("/users/:email", async (req, res) => {
const email = req.params.email;
const query = { email: email };
const user = await usersCollection.findOne(query);
let isAdmin = false;
if (user?.role === "admin") {
isAdmin = true;
}
// localhost:5000/users/admin#admin.com will show true
res.json({ admin: isAdmin });
});
//GET API (Bookings)
app.get("/bookings", async (req, res) => {
let query = {};
const email = req.query.email;
if (email) {
query = { email: email };
}
const result = await bookingsCollection.find(query).toArray();
res.send(result);
});
//GET Dynamic (Bookings)
app.get("/bookings/:id", async (req, res) => {
const id = req.params.id;
const query = { _id: ObjectId(id) };
const result = await bookingsCollection.findOne(query);
res.send(result);
});
//GET Dynamic (products)
app.get("/Devices/:id", async (req, res) => {
const id = req.params.id;
const query = { _id: ObjectId(id) };
const result = await djiPackages.findOne(query);
res.send(result);
});
//GET (testimonials)
app.get("/testimonials", async (req, res) => {
const result = await testimonialCollection.find({}).toArray();
res.send(result);
});
// ==========================POST API=========================
//POST API (dji Package)
app.post("/Devices", async (req, res) => {
const newTours = req.body;
const result = await djiPackages.insertOne(newTours);
res.send(result);
});
//POST API (users)
app.post("/users", async (req, res) => {
const user = req.body;
const result = await usersCollection.insertOne(user);
console.log(result);
res.send(result);
});
//POST API (Bookings )
app.post("/bookings", async (req, res) => {
const newBooking = req.body;
const result = await bookingsCollection.insertOne(newBooking);
res.send(result);
});
//POST API (Testimonials )
app.post("/testimonials", async (req, res) => {
const newBooking = req.body;
// console.log(newBooking);
const result = await testimonialCollection.insertOne(newBooking);
res.send(result);
});
// ======================DELETE API ========================
//DELETE API(Bookings)
app.delete("/bookings/:id", async (req, res) => {
const id = req.params.id;
const query = { _id: ObjectId(id) };
const result = await bookingsCollection.deleteOne(query);
res.send(result);
});
//DELETE API(drone)
app.delete("/Devices/:id", async (req, res) => {
const id = req.params.id;
const query = { _id: ObjectId(id) };
const result = await djiPackages.deleteOne(query);
res.send(result);
});
// =================Update API====================
app.put("/bookings/:id", async (req, res) => {
const id = req.params.id;
const newStatus = req.body;
const query = { _id: ObjectId(id) };
const options = { upsert: true };
const updateDoc = {
$set: {
data: newStatus.newData,
},
};
const result = await bookingsCollection.updateOne(
query,
updateDoc,
options
);
res.send(result);
});
//upsert Google user data
app.put("/users", async (req, res) => {
const user = req.body;
const filter = { email: user.email };
const options = { upsert: true };
const updateDoc = { $set: user };
const result = await usersCollection.updateOne(
filter,
updateDoc,
options
);
res.json(result);
});
// add admin role
app.put("/users/admin", async (req, res) => {
const user = req.body;
const filter = { email: user.email };
const updateDoc = { $set: { role: "admin" } };
const result = await usersCollection.updateOne(filter, updateDoc);
res.json(result);
});
});
} finally {
// await client.close();
}
}
Today I am facing a silly problem after deploying to Heroku. I have a React front-end. And express back-end. It is a social media app. So in this app, I have a profile page for users. In this page I am using a back-end route to fetch the data of the user. So everything remains good. But once I refresh the page, it starts showing the JSON object coming from the back-end
Before refresh.
after refresh
I am getting this problem after deployment only. I am sharing all of my code which I have written to deploy it to heroku
Server - package.json
{
"name": "server",
"version": "1.0.0",
"description": "Back-end of the dev-media front-end",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node app.js",
"heroku-postbuild": "NPM_CONFIG_PRODUCTION=false npm install --prefix client && npm run build --prefix client"
},
"keywords": [
"devr",
"dev-media"
],
"author": "Ratul-oss",
"license": "ISC",
"dependencies": {
"bcrypt": "^5.0.1",
"cookie-parser": "^1.4.5",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"mongoose": "^5.11.15",
"validator": "^13.5.2"
}
}
server - App.js
require("dotenv").config();
const express = require("express");
const routes = require("./routes/routes");
const cors = require("cors");
const app = express();
const port = process.env.PORT || 8000;
app.use(routes);
app.use(cors());
if (process.env.NODE_ENV === "production") {
app.use(express.static("client/build"));
}
app.listen(port, () => console.log(`Listening to http://localhost:${port}`));
And you may also checkout the routes.js where all of my back-end routes/codes are written
const cookieParser = require("cookie-parser");
const express = require("express");
const UserData = require("../models/user");
const routes = express.Router();
require("../dbConnection");
const auth = require("../middlewares/auth");
const cors = require("cors");
const Posts = require("../models/posts");
const bcrypt = require("bcrypt");
const Comments = require("../models/comment");
routes.use(express.json());
routes.use(express.urlencoded({ extended: false }));
routes.use(cookieParser());
routes.use(cors());
// * all the get routes starts from here
routes.get("/auth", auth, (req, res) => {
res.status(200).send(req.user);
});
// for getting the data of a single user by the id
routes.get("/user/:id", async (req, res) => {
try {
const id = req.params.id;
const user = await UserData.findOne({ _id: id });
res.status(201).send(user);
} catch (err) {
res.status(404).json({ err: "User not found" });
}
});
// for getting the data of all users
routes.get("/users", async (req, res) => {
try {
const users = await UserData.find();
res.status(200).send(users);
} catch (err) {
res.status(400).json({ err: "Something is wrong" });
}
});
// for logging out the user
routes.get("/logout", auth, async (req, res) => {
try {
req.user.tokens = req.user.tokens.filter(
(token) => token.token !== req.token
);
res.clearCookie("jwt");
await req.user.save();
res.status(200).send("Succefuly logged out");
} catch (err) {
console.log(err, "from the routes line 23");
}
});
// for getting all the followers
routes.get("/followers/:id", async (req, res) => {
try {
const id = req.params.id;
const user = await UserData.findOne({ _id: id });
res.send(user);
} catch (err) {
console.log(err);
}
});
// for recieving all the posts
routes.get("/posts", async (req, res) => {
try {
const posts = await Posts.find();
res.send(posts);
} catch (err) {
console.log(err);
}
});
// to verify the user posts
routes.get("/post/:id", async (req, res) => {
try {
const id = req.params.id;
const posts = await Posts.find({ userId: id });
res.send(posts);
} catch (err) {
console.log(err);
}
});
// for getting the single post according to the post id
routes.get("/posts/:id", async (req, res) => {
try {
const id = req.params.id;
const post = await Posts.findOne({ _id: id });
res.status(200).send(post);
} catch (err) {
res.status(404).json({ err: "Post Not Found" });
}
});
// for getting the specific comments of a post
routes.get("/comments/:id", async (req, res) => {
try {
const id = req.params.id;
const comments = await Comments.find({ postId: id });
res.send(comments);
} catch (err) {
console.log(err);
}
});
// * all the delete routes starts from here
// for deleting the use account
routes.delete("/deleteAccount/:id", async (req, res) => {
try {
const id = req.params.id;
await UserData.findByIdAndRemove(id).exec();
res.clearCookie("jwt");
res.send("Account Deleted");
} catch (err) {
console.log(err);
}
});
// for deleting the post
routes.delete("/deletepost", async (req, res) => {
try {
const id = req.body.id;
await Posts.findByIdAndRemove(id).exec();
res.send("Post deleted");
} catch (err) {
console.log(err);
}
});
// for deleting a comment
routes.delete("/deleteComment/:id", async (req, res) => {
try {
const id = req.params.id;
await Comments.findByIdAndRemove(id).exec();
res.status(200).send("Deleted");
} catch (err) {
console.log(err);
}
});
// * all the post routes starts from here
// for registering the user
routes.post("/register", async (req, res) => {
try {
const {
name,
email,
bio,
password,
conPass,
country,
gender,
profession,
} = req.body;
if (
(!name, !email, !password, !conPass, !country, !gender, !profession, !bio)
) {
res.status(422).json({ err: "Please fill all the fields properly" });
}
const user = new UserData({
name,
email,
bio,
password,
conPass,
country,
gender,
profession,
});
const emailExists = await UserData.findOne({ email: email });
if (emailExists) {
res.status(401).json({ err: "Email already exists" });
}
if (password !== conPass) {
res.status(403).json({ err: "Password doesn't matched" });
} else if (password === conPass && !emailExists) {
const token = await user.generateToken();
res.cookie("jwt", token);
await user.save();
}
res.status(200).json({ success: "Your account has been registered" });
} catch (err) {
res.status(400).send("Something went wrong");
}
});
// the login route
routes.post("/loginuser", async (req, res) => {
try {
const { email, password } = req.body;
const user = await UserData.findOne({ email: email });
const isMatched = await bcrypt.compare(password, user.password);
if (isMatched) {
const token = await user.generateToken();
res.cookie("jwt", token);
res.status(200).json({ success: "Loggin Successful" });
} else if (!isMatched) {
res.status(403).json({ err: "Your login details are invalid" });
}
} catch (err) {
res.status(400).json({ err: "Invalid Credentials" });
}
});
// for posting any post
routes.post("/postsomething", async (req, res) => {
try {
const name = req.body.name;
const text = req.body.text;
const userId = req.body.userId;
const time = req.body.time;
const date = req.body.date;
if (!text) {
res.status(400).json({ err: "Please type something!" });
}
const post = new Posts({
name: name,
date: date,
time: time,
body: text,
userId: userId,
like: 0,
});
await post.save();
res.status(200).json({ success: "Your Post has been created" });
} catch (err) {
res.status(500).send(err);
}
});
// for posting a comment
routes.post("/postComment", async (req, res) => {
try {
const postId = req.body.postId;
const user = req.body.user;
const commentText = req.body.comment;
const userName = req.body.userName;
const comment = new Comments({
userName,
commentText,
user,
postId,
time: new Date().toLocaleTimeString(),
date: new Date().toLocaleDateString(),
});
await comment.save();
res.status(200).send("Comment Posted");
} catch (err) {
console.log(err);
}
});
// * all the put request starts from here
// for updating the user
routes.put("/updateUser", async (req, res) => {
try {
const { name, email, bio, profession, userId } = req.body;
await UserData.findById(userId, (err, updatedUser) => {
if (name) {
updatedUser.name = name;
}
if (email) {
updatedUser.email = email;
}
if (bio) {
updatedUser.bio = bio;
}
if (profession) {
updatedUser.profession = profession;
}
updatedUser.save();
res.status(200).send("Informations has been updated");
});
} catch (err) {
res
.status(400)
.send(
"Please fill all the fields. If you don't want to update on of them, please type the previous one"
);
}
});
// for following any user
routes.put("/followUser", async (req, res) => {
try {
const followerUser = req.body.authenticateduser; // follower
const followingUser = req.body.user; // this guy will get the follow
await UserData.findById(followingUser._id, (err, user) => {
// when any user will click on the follow button in the front-end, his / her data will be
// stored in the followers field as an object
user.followers = user.followers.concat({ follower: followerUser });
user.save();
res.send("Followed");
});
} catch (err) {
console.log(err);
}
});
// to unfollow an user
routes.put("/unfollowUser", async (req, res) => {
try {
const followerUser = req.body.authenticateduser; // unfollower
const followingUser = req.body.user; // this guy will get the unfollow
await UserData.findById(followingUser._id, (err, user) => {
user.followers = user.followers.filter((follower) => {
return follower.follower._id !== followerUser._id;
});
user.save();
res.send("Unfollowed");
});
} catch (err) {
console.log(err);
}
});
// for liking a post
routes.put("/likePost", async (req, res) => {
try {
const postId = req.body.postId;
const liker = req.body.user;
await Posts.findById(postId, (err, post) => {
post.like = post.like + 1;
post.likers = post.likers.concat({ liker: liker });
post.save();
res.send("Liked");
});
} catch (err) {
console.log(err);
}
});
// for unliking a post
routes.put("/unlikePost", async (req, res) => {
try {
const postId = req.body.postId;
const liker = req.body.user;
await Posts.findById(postId, (err, post) => {
post.like = post.like - 1;
post.likers = post.likers.filter(
(likerUser) => likerUser.liker._id !== liker._id
);
post.save();
res.send("unliked");
});
} catch (err) {
console.log(err);
}
});
module.exports = routes;
You may check out the app I have deployed and figure out the problem https://devr-dev-media.herokuapp.com/. At First open an account then go to your profile page, then try to reload. Your will face the problem.
If you need more information, let me know. Please help me fix that problem with deployment. Thanks for the time :) Have a great day.
The route serving your page in React and the route on your backend are the same that is one of the possible cause. To solve the issues change the name of one maybe add "s" if you wish to maintain the same name. example
instead of
node server.js
`router.get('/name',(req,res)=>{}`
React App.js
<Router>
<Routes>
<Route path="/name" element={<Home/>}/>
</Routes>
</Router>
Try adding "s"
node server.js
`router.get('/names',(req,res)=>{}`
React App.js
<Router>
<Routes>
<Route path="/name" element={<Home/>}/>
</Routes>
</Router>
I'm using Mysql in my Express app
i hashed users pass using bcryptjs in mysql db and its fine.
using this code :
// register
router.post("/register", async (req, res) => {
const hashed = await bcrypt.hash(req.body.pass, 10);
const user = {
uname: req.body.uname,
phone: req.body.phone,
pass: hashed
};
let sql = "INSERT INTO user SET ? ";
db.query(sql, user, (err, result) => {
if (err) throw err;
console.log(`${user.uname} INSERTED INTO users`);
});
});
// GET USERS
router.get("/users", (req, res) => {
db.query("SELECT * FROM user", (err, results) => {
if (err) {
return res.send(err);
} else {
return res.json({
data: results
});
}
});
});
but when i want to log in users and let bcrypt compare requested pass with user pass it will give me this err :
SyntaxError: Unexpected identifier
And this is what i tried :
// loggin
router.post("/login", async (req, res) => {
var username = req.body.uname;
var password = req.body.pass;
db.query(
"SELECT pass FROM user WHERE uname = ?",
[username],
(err, result, fields) => {
try {
if (await bcrypt.compare(password, result)) {
console.log('Success')
}
} catch {
console.log('catched')
}
}
);
});
💡 The only one reason why you got some error, it's because you're using await in a function without async
👨🏻🏫 You can use this code below 👇:
router.post("/login", async (req, res) => {
var username = req.body.uname;
var password = req.body.pass;
db.query(
"SELECT pass FROM user WHERE uname = ?",
[username],
async (err, result, fields) => {
try {
// if you're using mysql2, don't forget to change `result` with `result[0].pass`.
// you can console.log(result) to see where is the field of your password plain text
const isPassword = await bcrypt.compare(password, result);
console.log(isPassword); // true
} catch(ex) {
console.log(ex); // false
}
}
);
});
I hope it's can help you 🙏.
I'm working with PostgreSQL and NodeJS with its "PG Module".
CRUD works but sometimes doesn't update automatically the views when i save or delete some item. this is my code and I think that the error is here but i cannot find it, i tried everything :'(
Error Message:
const controller = {};
const { Pool } = require('pg');
var connectionString = 'postgres://me:system#localhost/recipebookdb';
const pool = new Pool({
connectionString: connectionString,
})
controller.list = (request, response) => {
pool.query('SELECT * FROM recipes', (err, result) => {
if (err) {
return next(err);
}
return response.render('recipes', { data: result.rows });
});
};
controller.save = (req, res) => {
pool.query('INSERT INTO recipes(name, ingredients, directions) VALUES ($1, $2, $3)',
[req.body.name, req.body.ingredients, req.body.directions]);
return res.redirect('/');
};
controller.delete = (req, res) => {
pool.query('DELETE FROM RECIPES WHERE ID = $1', [req.params.id]);
return res.redirect('/');
}
module.exports = controller;
PD: CRUD works but sometimes appears that error.
This error occurs when you sent a response before and then you try to send response again. For this you have to check if there is any piece of code that is sending your response twice. Sometimes it happens due to asynchronous behavior of nodejs. Sometimes a process will be in event loop and we send response and when it finishes execution response will be sent again. So You can use callbacks or async await to wait for execution.
Callback
const controller = {};
const { Pool } = require('pg');
var connectionString = 'postgres://me:system#localhost/recipebookdb';
const pool = new Pool({
connectionString: connectionString,
})
controller.list = (request, response) => {
pool.query('SELECT * FROM recipes', (err, result) => {
if (err) {
return next(err);
}
return response.render('recipes', { data: result.rows });
});
};
controller.save = (req, res) => {
pool.query('INSERT INTO recipes(name, ingredients, directions) VALUES ($1, $2,$3)',
[req.body.name, req.body.ingredients, req.body.directions],function(err,resp)
{
if(err){
console.log(err)
}else{
return res.redirect('/');
}
});
};
controller.delete = (req, res) => {
pool.query('DELETE FROM RECIPES WHERE ID = $1', [req.params.id],function(err,resp){
if(err){
console.log(err)
}else{
return res.redirect('/');
}
});
}
module.exports = controller;
Or You can also use async await to wait for execution and then send response.
Async/Await
const controller = {};
const { Pool } = require('pg');
var connectionString = 'postgres://me:system#localhost/recipebookdb';
const pool = new Pool({
connectionString: connectionString,
})
controller.list = async(request, response) => {
try{
const result = await pool.query('SELECT * FROM recipes');
return response.render('recipes', { data: result.rows });
}
catch(err){
return next(err);
}
};
controller.save = async(req, res) => {
try{
await pool.query('INSERT INTO recipes(name, ingredients, directions) VALUES ($1, $2,$3)',[req.body.name, req.body.ingredients, req.body.directions]);
return res.redirect('/');
}
catch(err){
return next(err);
}
};
controller.delete = async(req, res) => {
try{
await pool.query('DELETE FROM RECIPES WHERE ID = $1', [req.params.id]);
return res.redirect('/');
}catch(err){
console.log(err);
}
}
module.exports = controller;
Check res.send() should not call two times.
In Controller
const getAll = function(req, res){
res.send(service.getAll(req,res));
}
In Service
const Type = require("../models/type.model.js");
exports.getAll = (req, res) => {
Type.getAll((err, data) => {
res.send(data);
});
};
Above res.send(data); two-time calling will create a problem. better to use
const getAll = function(req, res){
service.getAll(req,res);
}
You need to embed your response in the callback to the query. Since the call is asynchronous, sending the response earlier will terminate the call stack never waiting for the webapi(Behaviour may vary).
controller.delete = (req, res) => {
pool.query('DELETE FROM RECIPES WHERE ID = $1', [req.params.id],(err, result)
=> {
// error handling can be done accordingly
return res.redirect('/');
})
}