Connecting two tables with Node.Js Express - node.js

I've looked around on the web for solutions but there doesn't seem to be an answer relevant to mine. So I would like some help on this, please. Here I have two tables I need to connect and list on the React file. game table and users table, at the moment I am only able to display game table.
Server/index.js
const express = require("express");
const app = express();
const cors = require("cors");
const pool = require("./db");
//middleware
app.use(cors());
app.use(express.json()); //req.body
app.get("/af", async (req, res) => {
try {
const allTodos = await pool.query("SELECT game.*, users.* FROM users INNER JOIN game ON users.game_code = game.game_code; ");
res.json(allTodos.rows);
} catch (err) {
console.error(err.message);
}
});
Client/List.js
const List = () => {
const [af, setAF] = useState([]);
const getTodos = async() => {
try{
const response = await fetch("http://localhost:5000/af");
const jsonData = await response.json();
setAF(jsonData);
}catch(err){
console.error(err.message);
}
}
useEffect(() => {
getTodos();
}, []);
return(
<Fragment>
{" "}
<table className="table mt-5 text-center">
<thead>
<tr>
<th>game_code</th>
<th>user_code</th>
</tr>
</thead>
<tbody>
{af.map(game => (
<tr key = {game.game}>
<td>{game.game_code}</td>
<td>{game.game_location}</td>
))}
</tbody>
</table>
</Fragment>
export default List;

Related

My API data does not show up when calling from Nodejs

Below is my code to get data from an API and display on my server, the data comes in but does not display on the screen :
const express = require('express');
const router = express.Router();
const data = require('../data');
const peopleData = data.people;
router.get('/', async (req, res) => {
try {
const peopleList = await peopleData.getPeople();
res.render('people/user',{peopleList:peopleList});
} catch (e) {
res.status(500).send();
}
});
module.exports = router;
Data function:
require("util").inspect.defaultOptions.depth = null;
const axios = require('axios');
async function getPeople(){
const { data } = await axios.get('https://gist.githubusercontent.com/SwayamShah97/0f2cb53ddfae54eceea083d4aa8d0d65/raw/d7d89c672057cf7d33e10e558e001f33a10868b2/people.json');
return data; // this will be the array of people objects
}
module.exports = {
getPeople
}
Handlebars:
<div>
<table>
<tr>
<th>ID</th>
<th>First Name</th>
<th>Last Name</th>
</tr>
{{#each peopleList}}
<tr>
<td>{{id}}</td>
<td>{{firstName}}</td>
<td>{{lastName}}</td>
</tr>
{{/each}}
</table>
</div>
Not sure why nothing displays, I console log and the data comes in fine.

TypeError: users.map is not a function in Mern

I am trying to fetch data from backend, I want to load all data which are in database, when I load function then getting an error like "User.map is not a function", please let me know where am wrong.
User.js
import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import { getUsers } from "./apis";
const UserData = () => {
const [users, setUser] = useState([]);
useEffect(() => {
AllUsers();
}, []);
const AllUsers = async () => {
const response = await getUsers();
console.log(response.data);
setUser(response.data ? response.data : []);
};
return (
<div>
<div className="container">
<table className="table table-hover table-bordered mt-5">
<thead>
<tr>
{/* <th scope="col">No</th> */}
<th scope="col">Title</th>
<th scope="col">Details</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
{users.map((user, index) => (
<tr key={index}>
<th scope="row">{user.id}</th>
<td>{user.title}</td>
<td>{user.description}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
);
};
Api.js
I have added api.js file please check it , and let me know where am wrong
export default UserData;
import Axios from "axios";
const url = "http://localhost:3000/";
export const getUsers = async (id) => {
id = id || "";
return await Axios.get(`${url}/${id}`);
};
export const deleteUser = async (id) => {
return await Axios.delete(`${url}/${id}`);
};
You can use Optional chaining (?.) for check the data is available or not. Because while API's is calling data not set in your state. It's might be a undefined.
const adventurer = {
name: 'Alice',
cat: {
name: 'Dinah'
}
};
const dogName = adventurer.dog?.name;
console.log(dogName);
In your case do with this way.
{users?.map((user, index) => (
<tr key={index}>
<th scope="row">{user.id}</th>
<td>{user.title}</td>
<td>{user.description}</td>
</tr>
))}
import Axios from "axios";
const url = "http://localhost:3000/";
export const getUsers = async (id) => {
id = id || "";
return await Axios.get(`${url}/${id}`);
};
export const deleteUser = async (id) => {
return await Axios.delete(`${url}/${id}`);
};

Change state and update it in the database

I'm working on a web app to track fruits vendor stock using React.js, MongoDB, Node.js, and Express. I called my database endpoints to render the data in the table. Now I try to increment and decrement the stock amount using a button, but when I try to set the new state, it doesn't work. I try to change the state by clicking, then update the new state in the database. Any advice?
FruitTable component:
import Reac, { Component } from 'react';
import * as ReactBootstrap from 'react-bootstrap';
import axios from 'axios';
import Button from 'react-bootstrap/Button';
class FruitTable extends Component {
constructor(props) {
super(props)
this.state = {
fruits: []
}
this.handleClick = this.handleClick.bind(this)
}
componentDidMount() {
axios.get('http://localhost:5000/fruits/')
.then(res => {
this.setState({
fruits: res.data
});
})
.catch((error) => {
console.log(error)
})
}
handleClick = () => {
const fruits = [...this.state.fruits]
this.setState({fruits: this.state.fruits[1] +1})
}
render() {
return(
<div>
<h1>Fruit Vendor Stock</h1>
<ReactBootstrap.Table striped bordered hover size="sm">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Stock</th>
<th>Price</th>
<th>Add/Reomve</th>
</tr>
</thead>
<tbody>
{
this.state.fruits.map((fruit, index) => (
<tr>
<th scope="row">{index + 1}</th>
<td>{fruit.name}</td>
<td>{fruit.stock}</td>
<td>{fruit.price}</td>
<td>
<div className="mb2">
<Button className="btn btn-primary btn-sm"
onClick={this.handleClick}
>Add</Button>{' '}
<Button className="btn btn-danger btn-sm"
>Remove</Button>
</div>
</td>
</tr>
))
}
</tbody>
</ReactBootstrap.Table>
</div>
)
};
}
export default FruitTable;
FruitsData.model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const fruits = new Schema({
name: { type: String, required: true },
stock: { type: Number, required: true },
price: { type: Number, required: true },
}, {
});
const Fruits = mongoose.model('Fruits', fruits);
module.exports = Fruits;
-Routes:
const router = require('express').Router();
let Fruit = require('../models/fruit_data');
router.route('/').get((req, res) => {
Fruit.find()
.then(fruits => res.json(fruits))
.catch(err => res.status(400).json('Error: ' + err));
});
router.route('/add').post((req, res) => {
const name = req.body.name;
const stock = Number(req.body.stock);
const price = Number(req.body.price);
const newFruit = new Fruit({
name,
stock,
price,
});
newFruit.save()
.then(() => res.json('Fruit has been added!'))
.catch(err => res.status(400).json('Error: ' + err));
});
router.route('/:id').get((req, res) => {
Fruit.findById(req.params.id)
.then(Fruit => res.json(Fruit))
.catch(err => res.status(400).json('Error: ' + err));
});
router.route('/:id').delete((req, res) => {
Fruit.findByIdAndDelete(req.params.id)
.then(() => res.json('Fruit has deleted.'))
.catch(err => res.status(400).json("Error: " + err));
});
router.route('/update/:id').put((req, res, next) => {
Fruit.findByIdAndUpdate(req.params.id, {
$set: req.body
}, (error, data) => {
if(error) {
return next(error);
console.log(error)
} else {
res.json(data)
console.log('Stock has been updated')
}
})
})
module.exports = router;
-Server.js:
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
require('dotenv').config();
const app = express();
const port = process.env.PORT || 5000;
app.use(cors());
app.use(express.json());
const uri = process.env.ATLAS_URI;
mongoose.connect(uri, { useNewUrlParser: true });
const connection = mongoose.connection;
connection.once('open', () => {
console.log("MongoDb database connection established successfully!!")
})
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
const fruitsRouter = require('./routes/fruit');
app.use('/fruits', fruitsRouter);
app.listen(port, () => {
console.log(`Server is running on port: ${port}`);
})
-App.js:
import "./App.css";
import React, { Component, useState, useEffect } from "react";
import FruitTable from "./Components/fruitTable";
import "bootstrap/dist/css/bootstrap.min.css";
import { sendEmail } from "./service/emailService";
import axios from 'axios';
function App() {
return (
<div className="App">
<FruitTable />
</div>
);
}
export default App;
The state update in handleClick isn't correct, it is taking the 1th element value, adding 1 to it, and setting this as the this.state.fruits state value. This breaks the state invariant of fruits being an array. This is likely the "crash" you are seeing as a non-array value is attempted to be mapped.
handleClick = () => {
const fruits = [...this.state.fruits]
this.setState({
fruits: this.state.fruits[1] +1 // <-- mutates state invariant!!
})
}
The code also isn't passing a reference to which index or fruit it is trying to update.
According to your schema the fruit items have 3 properties, name, stock, and price. For this solution I'll assume that name is sufficiently unique for identification purposes and that you are incrementing/decrementing the stock quantity.
handleClick = (name, addQuantity = 1) => () => {
this.setState(prevState => ({
fruits: prevState.fruits.map(fruit =>
fruit.name === name
? { ...fruit, stock: fruit.stock + addQuantity}
: fruit
)
}));
}
Now you need to pass the currently mapped fruit item's name property to the handler when mapping.
{this.state.fruits.map((fruit, index) => (
<tr key={fruit.name}>
<th scope="row">{index + 1}</th>
<td>{fruit.name}</td>
<td>{fruit.stock}</td>
<td>{fruit.price}</td>
<td>
<div className="mb2">
<Button
className="btn btn-primary btn-sm"
onClick={this.handleClick(item.name, 1)} // <-- add one
>
Add
</Button>{' '}
<Button
className="btn btn-danger btn-sm"
onClick={this.handleClick(item.name, -1)} // remove one
>
Remove
</Button>
</div>
</td>
</tr>
))}

How do I properly update my Postgres Database in Node.js?

The Problem: syntax error at or near "$"
The Context: My App does two CRUD operations - Update & Read Data from a Postgres database. It successfully reads data from the database and displays on the frontend. However, it fails to update the database when I query it to do so. It throws an error that 'syntax error at or near "$"'.
So far, I have failed to debug the error successfully.
The Stacks: Postgres, Node.js, React
The Query (BackEnd):
//burrow a book
app.post("/books/:id", async (req, res) => {
try {
const { id } = req.params;
const copies = await pool.query('SELECT copies FROM books WHERE book_id = $id', [id]);
const stock = copies - 1;
const updateBook = await pool.query("UPDATE books SET copies = $1 WHERE book_id = $2", [stock, id]);
const allBooks = await pool.query("SELECT * FROM books");
res.json(allBooks.rows);
} catch (err) {
console.error(err.message);
}
});
The Function(FrontEnd):
async function burrowbook(id) {
try {
const res = await fetch(`http://localhost:5000/books/${id}` , {method: "POST"});
console.log(res);
// setbooks(jsonData);
// console.log(jsonData);
} catch (err) {
console.error(err.message);
}
}
The Full React Component(FrontEnd):
import React, { Fragment, useEffect, useState } from 'react';
const ListBooks = () => {
const [books, setbooks] = useState([]);
async function burrowbook(id) {
try {
const res = await fetch(`http://localhost:5000/books/${id}` , {method: "POST"});
console.log(res);
// setbooks(jsonData);
// console.log(jsonData);
} catch (err) {
console.error(err.message);
}
}
const getBooks = async () => {
try {
const response = await fetch("http://localhost:5000/books");
const jsonData = await response.json();
setbooks(jsonData);
// console.log(jsonData);
} catch (err) {
console.error(err.message);
}
}
useEffect(() => {
getBooks();
}, []);
return (<Fragment>
<div class="container ">
<h1 class="text-center mt-5">Wakanda Library</h1>
</div>
<table class="table table-hover table-dark text-center mt-5">
<thead>
<tr>
<th scope="col">Book ID</th>
<th scope="col">Title</th>
<th scope="col">Author</th>
<th scope="col">Year</th>
<th scope="col">Stock</th>
<th scope="col">Burrow</th>
<th scope="col">Return</th>
</tr>
</thead>
<tbody>
{books.map(book => (
<tr key={book.book_id}>
<td>{book.book_id} </td>
<td>{book.title} </td>
<td>{book.author} </td>
<td>{book.publish_year} </td>
<td>{book.copies} </td>
<td><button
className="btn btn-success btn-circle btn-md"
onClick={() => burrowbook(book.book_id)}
>
Burrow
</button></td>
<td><button
className="btn btn-primary btn-circle btn-md"
// onClick={() => returnBook(book.book_id)}
>
Return
</button></td>
</tr>
))}
</tbody>
</table>
</Fragment>);
};
export default ListBooks;
The Full index.js script(BackEnd):
const express = require("express");
const app = express();
const cors = require('cors');
const pool = require('./db');
//middleware
app.use(cors());
app.use(express.json()); //req.body
//ROUTES//
//login user
//register user
//list of books in library
app.get("/books", async (req, res) => {
try {
const allBooks = await pool.query("SELECT * FROM books");
res.json(allBooks.rows);
} catch (err) {
console.error(err.message);
}
});
//burrow a book
app.post("/books/:id", async (req, res) => {
try {
const { id } = req.params;
console.log(id);
const copies = await pool.query('SELECT copies FROM books WHERE book_id = $id', [id]);
console.log("b");
const stock = copies - 1;
console.log("c")
const updateBook = await pool.query("UPDATE books SET copies = $1 WHERE book_id = $2", [stock, id]);
console.log("d")
const allBooks = await pool.query("SELECT * FROM books");
console.log("heee")
res.json(allBooks.rows);
} catch (err) {
console.error(err.message);
}
});
//return a book
app.put("/booksreturn/:id", async (req, res) => {
try {
const { id } = req.params;
const { copies } = req.body;
const returnBook = await pool.query(
"UPDATE books SET copies = $copies WHERE book_id = $id",
[copies = parseFloat(copies) + 1, id]
);
res.json("Book was returned!");
} catch (err) {
console.error(err.message);
}
});
//list of books in users possession
app.listen(5000, () => {
console.log("Baba... server don start on top port 5000.")
});

I can't get information from json to pug variables. Handlebars can see information, pug can't see. but code the same

I can't get information from json to pug variables. The pug knows how many elements in json. but dont see title, price and etc. If i use Handlebars, not pug - code works!!! I don't understand why Handlebars works. pug not working. i trid use like this p #{price} and like this p=price. i don't know what is the problem...
index.js
const express = require('express')
const app = express()
const path = require('path')
const pug = require('pug')
//const homeRoutes = require('./routes/home')
//const addRoutes = require('./routes/add')
const coursesRoutes = require('./routes/courses')
app.set('view engine', 'pug')
app.set('views', './views')
app.use(express.static('public'))
app.use(express.urlencoded({extended: true}))
app.use('/', homeRoutes)
app.use('/add', addRoutes)
app.use('/courses', coursesRoutes)
const PORT = process.env.PORT || 3000
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`)
})
courses.js (router)
const {Router} = require('express')
const Course = require('../models/course')
const router = Router()
router.get('/', async (req, res) => {
const courses = await Course.getAll()
res.render('courses', {
title: 'Курсы',
isCourses: true,
courses
})
})
module.exports = router
course.js (Model)
const { v4: uuid } = require('uuid');
const fs = require('fs')
const path = require('path')
class Course {
constructor(title, price, img) {
this.title = title
this.price = price
this.img = img
this.id = uuid()
}
toJSON() {
return {
title: this.title,
price: this.price,
img: this.img,
id: this.id
}
}
async save() {
const courses = await Course.getAll()
courses.push(this.toJSON())
return new Promise((resolve, reject) => {
fs.writeFile(
path.join(__dirname, '..', 'data', 'courses.json'),
JSON.stringify(courses),
(err) => {
if (err) {
reject(err)
} else {
resolve()
}
}
)
})
}
static getAll() {
return new Promise((resolve, reject) => {
fs.readFile(
path.join(__dirname, '..', 'data', 'courses.json'),
'utf-8',
(err, content) => {
if (err) {
reject(err)
} else {
resolve(JSON.parse(content))
}
}
)
})
}
}
module.exports = Course
courses.json
[{"title":"Angular 8","price":"12000","img":"https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Angular_full_color_logo.svg/1200px-Angular_full_color_logo.svg.png","id":"8ae92db5-97f4-494c-ade8-a258d931d61e"},{"title":"Vue JS","price":"20000","img":"https://upload.wikimedia.org/wikipedia/commons/thumb/9/95/Vue.js_Logo_2.svg/1200px-Vue.js_Logo_2.svg.png","id":"b56de685-9bdf-4c4b-8302-80ad480732ef"},{"title":"erere","price":"1212","img":"232","id":"02787dc5-0ca2-4329-8acf-41b576981e3a"}]
courses.pug
block content
<h1>courses page</h1>
if courses.length
each cours in courses
.row
.col.s6.offset-s3
.card
.card-image
img(src="#{img}")
.card-content
span.card-title #{title}
p.price #{price}
.card-action
a(href="/courses/#{id}") Open course
else
p there are not courses
but if i use Handlebars. not pug -- code works!!!
{{#if courses.length}}
{{#each courses}}
<div class="row">
<div class="col s6 offset-s3">
<div class="card">
<div class="card-image">
<img src="{{img}}" alt="{{title}}">
</div>
<div class="card-content">
<span class="card-title">{{title}}</span>
<p class="price">{{price}}</p>
</div>
<div class="card-action">
Open course
</div>
</div>
</div>
</div>
{{/each}}
{{else}}
<p>There are nor courses</p>
{{/if}}
what i see if i use pug
what i see if i use handlebars
Inside the iteration, you can refer to the iteration variable (cours).
You cannot refer to its properties directly by their name (as variables).
You must use property accessors (dot or square brackets).
block content
<h1>courses page</h1>
if courses.length
each cours in courses
.row
.col.s6.offset-s3
.card
.card-image
img(src="#{cours.img}")
.card-content
span.card-title #{cours.title}
p.price #{cours.price}
.card-action
a(href="/courses/#{cours.id}") Open course
else
p there are not courses

Resources