React to pull SQL data from server - node.js

I figured out how to make a request to SQL server and post as JSON on the server side. I'm wondering how I can pull that data into the react side.
Server.js:
let pullTable = require('./actions/pullTable.js');
var express = require('express');
var app = express();
app.get('/', async (req, res, next) => {
try {
const result = await pullTable.pullTable();
return res.status(200).json(result);
} catch (error) {
next(error);
}
});
app.listen(5000, () => {console.log('Server is running..')});
SQL Request - pullTable.js:
var sql = require("mssql");
var express = require('express');
var app = express();
// config for your database
var config = {
user: 'user',
password: 'pass',
server: 'localhost',
database: 'Master'
};
const pullTable = async () => {
try {
const pool = await sql.connect(config);
const sqlQuery = 'SELECT * FROM Persons';
const result = await pool.request().query(sqlQuery);
return result.recordset;
} catch (err) {
throw err;
}
};
exports.pullTable = pullTable;
The code works fine up to here. I look at port 5000 and can see the JSON data being displayed from my server. Just not sure how to get this into React. This is my attempt at the react side (not including the App.js file - don't need help with that):
getData.js:
import React, { Component } from 'react';
class getData extends Component {
constructor(){
super();
this.state={
data:[],
}
}
componentDidMount(){
fetch('http://localhost:5000')
.then((Response)=>Response.json())
.then((findresponse)=>
{
this.setState({
data:findresponse,
});
});
}
render() {
return (
<div>
{
this.state.data.map((dynamicData)=>
<div>
<span>{dynamicData.LastName} </span>
<span>{dynamicData.FirstName}</span>
</div>
)
}
</div>
);
}
}
export default getData;
Just looking to display the first and last name of people in that SQL table.

#Shawn Yap pointed me in the right direction. Basically had to include the Access-Control-Allow-Origin header on the server script:
let pullTable = require('./actions/pullTable.js');
var express = require('express');
var app = express();
app.get('/', async (req, res, next) => {
try {
res.set('Access-Control-Allow-Origin', '*');
const result = await pullTable.pullTable();
return res.status(200).json(result);
} catch (error) {
next(error);
}
});
app.listen(5000, () => {console.log('Server is running..')});
Not sure if this even good code, but it's working.

Related

How to use router.get correctly?

I am getting data from mongodb and displaying on the routes but one of the routes does not work, below is my code:
routes:
const express = require('express');
const router = express.Router();
const data = require('../data');
const gymData = data.gyms;
router.get('/', async (req, res) => {
try {
let gymList = await gymData.getTopFive();
res.render('gymbars/gymlist',{gyms:gymList})
} catch (e) {
res.sendStatus(500);
}
});
router.get('/gymcreate',async(req,res) => {
try{
res.render('gymbars/creategym')
}
catch(e){
res.sendStatus(500);
}
});
module.exports = router;
index.js:
const gymRoutes = require('./gyms');
const constructorMethod = (app) => {
app.use('/gyms', gymRoutes);
app.use('*', (req, res) => {
res.status(404).json({ error: 'Not found' });
});
};
module.exports = constructorMethod;
handlebars creategym:
<div>
<h1> hello </h1>
</div>
The below route just throws internal server error whereas the other route works correctly
http://localhost:3000/gyms/gymcreate
I am not sure what I am doing wrong

How to fetch data from API in Node.js to a view in React.js

I tried to get data from my SQL Server Management Studio. I already made the the query inside API, so when I access those links using postman, it will retrieve data equals to the query inside those links. But when i want to show the data at page, it not comes out even though it already comes out at the console log. The error always changing, but never solved.
DbOperations Query
const config = require('./dbConfig');
const sql = require('mssql');
async function getRoles() {
try {
let pool = await sql.connect(/My Configuration Database/);
let products = await pool.request().query("SELECT [id],[division] FROM [FMLX_IME].[dbo].[ime.tbl_roles]");
return products.recordsets;
}
catch(error) {
console.log(error);
}
}
This is how I insert the function to API links
const express = require('express');
const cors = require('cors');
const app = express();
const bodyParser = require('bodyParser');
const Db = require('./dbOperations');
const router = express.Router();
const PORT = process.env.PORT || 3001;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors());
app.use('/api', router);
router.use((request, response, next) => {
console.log("============ MIDDLEWARE ============");
next();
});
router.route('/get-roles').get((request, response) => {
Db.getRoles().then(result => {
response.json(result);
console.log(result);
});
});
This how I tried to fetch the data, already tried so many ways but nothing works. Only success to retrieved the data if using API that already online or running, not from my localhost. (Already tried using axios too)
Class ManualTest extends React.Component {
constructor(props) {
super(props);
this.state = {
roles: [],
isLoaded: false
}
}
componentDidMount() {
fetch('http://localhost:3001/api/get-roles')
.then(result => console.log(result.json()))
.then(res => res.json())
.then(json => {
this.setState({
roles: json,
isLoaded: true
})
}).catch((err) => {
console.log(err);
});
}
render() {
const { isLoaded, roles } = this.state;
if(!isLoaded)
return <div>Loading...</div>
return (
<div className="App">
<ul>
{roles.map(role => (
<li key={role.id}>
ID: {role.id} || ROLE: {role.role}
</li>
))}
</ul>
</div>
);
}
}
export default ManualTest

How to display only searched results in the browser as response

I have a MongoDB collection that I search through by using a value from an input field using the $search operator and it works, when I console log the result it shows me only those documents that match the search, but I want them to be visible on the endpoint http://localhost:3001/search as well, but currently I get all the documents listed, how can I list the result of the search? I am trying with res.send(result); but it does not work. Here is my attempt:
// Requiring the dependencies
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
require('dotenv').config();
const mongoose = require('mongoose');
const PORT = process.env.PORT || 3001;
const BASE_URL = process.env.REACT_APP_BASE_URL;
const itemRoutes = express.Router();
let Comment = require('./comment.model');
app.use(cors());
app.use(bodyParser.json());
mongoose.connect(BASE_URL, { useNewUrlParser: true })
const connection = mongoose.connection;
connection.once('open', function () {
console.log('Connection to MongoDB established succesfully!');
});
let collection = connection.collection("posts_with_tags_test");
collection.createIndex(
{
postContent: 'text',
title: 'text'
}
);
itemRoutes.route('/search').post(async (req, res) => {
let result = await connection.collection("posts_with_tags_test").find({
$text: {
$search: req.body.queryString
}
}).toArray();
res.send(result);
console.log(result)
});
app.use('/search', itemRoutes);
app.listen(PORT, function () {
console.log('Server is running on' + ' ' + PORT);
})
and here is my input field:
import React, { Component } from "react";
import axios from "axios";
class Search extends Component {
getSearchQuery = () => {
const queryString = document.querySelector(
".search-input"
).value;
axios.post("http://localhost:3001/search", {
queryString: queryString,
});
console.log(queryString)
};
render() {
return (
<div>
<input
type="text"
className="search-input"
/>
<button type="submit" onClick={this.getSearchQuery}></button>
</div>
);
}
}
export default Search;
If you just access localhost:3001/search from a browser, it won't be visible because you aren't sending the data { queryString: "sample" } to be used in the query as req.body.queryString unless you're using Postman
If you're accessing it from frontend, in your React component's getSearchQuery, try using .then() on your axios.post() to receive the response from your backend
axios.post("http://localhost:3001/search", {
queryString: queryString,
}).then(response => {
console.log(response);
console.log(response.status);
console.log(response.data);
});

POST endpoint created with Node.js not found

I have a database in Mlab that is MongoDB that has two collections and I am trying to make a POST endpoint to which I can post whatever a user has entered in a commentbox. However I am doing something wrong, because when I test my endpoint with Postman it says 404 that the endpoint is not found. Trying to post via the commentbox does not work too ofcourse. This is the url to my post endpoint:
https://astroecstatic-express.herokuapp.com/comments. However if I run this in the browser it displays an empty array, so how come I get a 404 error when trying to POST? What am I doing wrong and how can I make my POST endpoint? Here is my node.js server:
// Requiring the dependencies
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
const PORT = process.env.PORT || 3001;
const itemRoutes = express.Router();
let Comment = require('./comment.model');
app.use(cors());
app.use(bodyParser.json());
mongoose.connect("mongodb://admin:SomeUSersecretpassword.mlab.com:41968/heroku_hc9xjmcl", { useNewUrlParser: true } )
const connection = mongoose.connection;
connection.once('open', function() {
console.log('Connection to MongoDB established succesfully!');
});
// Serve static assets
if(process.env.NODE_ENV === 'production') {
app.use(express.static('build'));
}
itemRoutes.route('/').get( async (req, res) => {
let collection = connection.collection("posts");
let response = await collection.find({})
.toArray();
res.send(response);
});
itemRoutes.route('/comments').get( async (req, res) => {
let collection = connection.collection("comments");
let response = await collection.find({})
.toArray();
res.send(response);
});
itemRoutes.route('/comments')
.post((req, res) => {
res.setHeader('Content-Type', 'application/json');
let comment = new Comment(req.body);
comment.save()
.then(comment => {
res.status(200).json({comment})
})
.catch(err => {
res.status(400).send('failed')
})
});
app.use('/', itemRoutes);
app.use('/comments', itemRoutes);
app.listen(PORT, function() {
console.log('Server is running on' + ' ' + PORT);
})
and my post component:
import React, { Component } from 'react';
import axios from 'axios';
class CommentBox extends Component {
constructor(props) {
super(props);
this.path = window.location.href;
this.postId = this.path.split("/").slice(-1)[0];
}
state = {
userComments: []
}
componentDidMount() {
const fetchPosts = async () => {
const res = await axios.get('https://astroecstatic-express.herokuapp.com/comments');
this.setState({...this.state, userComments: res.data})
};
fetchPosts();
}
getCommentData = (res) => {
let today = new Date();
let dd = String(today.getDate()).padStart(2, '0');
let mm = String(today.getMonth() + 1).padStart(2, '0'); //January is 0!
let yyyy = today.getFullYear();
today = mm + '/' + dd + '/' + yyyy;
const commentContent = document.querySelector(".comment-box-container__div-comment-box").textContent;
axios.post('https://astroecstatic-express.herokuapp.com/comments', {title: commentContent, date: today, commentId: this.postId })
window.location.reload();
}
render() {
let currentPostComments = this.state.userComments.filter((item) => {
return item.commentId === this.postId
})
return(
<div className="comment-box-container">
<div className="comment-box-container__div">
<button className="comment-box-container__post-comment-btn" onClick={this.getCommentData}> Post Comment</button>
<div className="comment-box-container__div-comment-box" contentEditable="true"></div>
</div>
<div className="comment-box-container__show-coments-section">
{currentPostComments.map(comment =>
<section>
<h3>{comment.date}</h3>
{comment.title}
</section>
)}
</div>
</div>
)
}
}
export default CommentBox;
Here's a simple way to create both a .get() and a .post() route for /comments on a router:
itemRoutes.get("/comments", function(req, res, next) {
// code here
});
itemRoutes.post("/comments", function(req, res, next) {
// code here
});
app.use(itemRoutes);
You can also use .route() instead like this:
itemRoutes.route("/comments").get(function(req, res, next) {
// code here
}).post(function(req, res, next) {
// code here
});
app.use(itemRoutes);
And, you don't even really have a compelling case for using a router for these two routes. You could also just do:
app.get("/comments", ...);
app.post("/comments", ...);
Or
app.route("/comments")
.get(...)
.post(...);
And, not even use a router for just two top level routes.

How could I make a global mongodb connection that I can access from other files

So I have this main server file index.js:
const express = require('express')
const app = express()
const route = require('./route')
app.use('/main', route)
app.listen(3000)
and then I have the route.js file:
const express = require('express')
const router = express.Router()
router.get('/', (req, res) => {
res.send('Hello from main')
})
module.exports = router
As the title implies, how could I make a global mongodb connection so that I don't have to make a new connection to the database on every route?
Thanks!
I'm surprised there is no answer on SO to this. The most common pattern is to initialize your database connection in a separate module and to import it in any file that needs it.
The below was taken from this longer article https://itnext.io/how-to-share-a-single-database-connection-in-a-node-js-express-js-app-fcad4cbcb1e and was written in callback style. I've updated it a little to be promise based below:
/* Callback Style */
const assert = require("assert");
const client = require("mongodb").MongoClient;
const config = require("../config");
let _db;
module.exports = {
getDb,
initDb
};
function initDb(callback) {
if (_db) {
console.warn("Trying to init DB again!");
return callback(null, _db);
}
client.connect(config.db.connectionString,
config.db.connectionOptions, connected);
function connected(err, db) {
if (err) {
return callback(err);
}
console.log("DB initialized - connected to: " +
config.db.connectionString.split("#")[1]);
_db = db;
return callback(null, _db);
}
}
function getDb() {
assert.ok(_db, "Db has not been initialized. Please called init first.");
return _db;
}
/******************************************************************/
//The client
const initDb = require("./db").initDb;
const getDb = require("./db").getDb;
const app = require("express")();
const port = 3001;
app.use("/", exampleRoute);
initDb(function (err) {
app.listen(port, function (err) {
if (err) {
throw err; //
}
console.log("API Up and running on port " + port);
});
);
function exampleRoute(req, res){
const db = getDb();
//Do things with your database connection
res.json(results);
}
Here's a promise based version without semi-colons which is how I might do it for itself. These functions would all become candidates for reuse between projects.
const assert = require("assert")
const client = require("mongodb").MongoClient
const config = require("../config")
let _db
module.exports = {
getDb,
initDb
}
function initDb() {
if (_db) {
console.warn("Trying to init DB again!");
return Promise.resolve(true)
}
return client.connect(config.db.connectionString,
config.db.connectionOptions)
}
function getDb() {
assert.ok(_db, "Db has not been initialized. Please called init first.")
return _db
}
//////////////////////
const {initDb, getDb} = require("./db")
const app = require("express")()
const port = 3001
app.use("/", exampleRoute)
initDb().
then(_ =>bootServer(port))
.catch(console.log)
function bootServer(port) {
app.listen(port, function (err) {
if (err) {
Promise.reject(err)
}
console.log("API Up and running on port " + port)
Promise.resolve()
})
}
function exampleRoute(req, res){
const db = getDb();
//Do things with your database connection
res.json(results);
}

Resources