I am building a React app that logs user input and saves it to a database. I have created a REST API using node.js Express to connect the app to the database.
I have succesfuly made a post request using Postman but cannot get it working with the react app because I recieve SyntaxError: Unexpected end of JSON input error.
I've tried solutions described on similar Stack Overflow posts but nothing has worked for me. As far as I can tell, I have formatted my json input correctly. One post indicated it could be to do with my Express API not returning correctly formatted JSON but this cannot be the case because postman receives JSON output after successful post.
Postman output
console output
stack trace
React App code
import logo from './logo.svg';
import './App.css';
import Submit from './Submit';
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
pic: "",
alive: "",
typeOfDeath: "",
comment: "",
geoLocation: ""
};
}
// code credit - https://github.com/lyhd/reactjs/blob/base64_encode/src/index.js
encodeFileBase64 = (file) => {
var reader = new FileReader();
if (file) {
reader.readAsDataURL(file);
reader.onload = () => {
var Base64 = reader.result;
console.log(Base64);
//setFileBase64String(Base64);
};
reader.onerror = (error) => {
console.log("error: ", error);
};
}
};
handleSubmit = async (evt) => {
evt.preventDefault();
const input = document.querySelector('input[type=file]');
const pic = input.files[0];
const pic_base64 = this.encodeFileBase64(pic);
const rbs = document.querySelectorAll('input[name="mortality"]');
let alive = false;
//code belongs to javascripttutorial.net/javascript-dom/javascript-radio-button/
for (const rb of rbs) {
if (rb.checked) {
alive = rb.value;
break;
}
}
const typeOfDeathDropDown = document.querySelector('#typeOfDeath');
const typeOfDeath = typeOfDeathDropDown.options[typeOfDeathDropDown.selectedIndex].value;
const comment = document.querySelector('#comment').value.trim();
const geoLocation = "placeholder";
//pleaceholder validation if statement, replace at a later date
if (1 > 0) {
console.log(alive,typeOfDeath,comment,geoLocation);
this.setState({
pic: pic_base64,
alive: alive,
typeOfDeath: typeOfDeath,
comment: comment,
geoLocation: geoLocation
});
const url = 'https://zapp.ogs17.brighton.domains/';
let jsonBody = JSON.stringify({
pic: pic_base64,
alive: alive,
typeOfDeath: typeOfDeath,
comment: comment,
geoLocation: geoLocation
});
console.log(jsonBody);
try {
const response = await fetch(url, {
method: 'POST',
headers: {'Content-Type':'application/x-www-form-urlencoded'},
body: jsonBody
});
await console.log(response);
const jsonData = await response.json();
this.setState({
loading: false,
records: jsonData.records
});
} catch (err) {
console.log(err);
this.setState({
loading: false,
records: []
});
}
}
}
render = () => {
return (
<div>
<h1>Zapp App - Pangolin Sightings</h1>
<form onSubmit={this.handleSubmit}>
<input type="file" accept="image/*" id="pic" />
<input id="alive" type="radio" name="mortality" />
<label htmlFor="alive">Alive</label>
<input id="deceased" type="radio" name="mortality" />
<label htmlFor="deceased">Deceased</label>
<br />
<label htmlFor="typeOfDeath">Type of Death:</label>
<select name="typeOfDeath" id="typeOfDeath">
<option value="fence_electrocution">Fence death: electrocution;</option>
<option value="fence_normal">Fence death: caught on non-electrified fence</option>
<option value="road">Road death</option>
<option value="other">Other</option>
</select>
<br />
<textarea name="comment" id="comment" defaultValue="comment"></textarea>
<br />
<button type="submit">Submit</button>
</form>
<Submit state={this.state} />
</div>
);
}
}
export default App;
Node.js Express Api code
const express = require('express');
const bodyParser = require('body-parser');
const db = require('./db');
const cors = require('cors');
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cors());
const port = 3000;
//https://stackoverflow.com/questions/18310394/no-access-control-allow-origin-node-apache-port-issue
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', '*');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
next();
});
async function getSighting(req) {
let status = 500, data = null;
try {
const oid = req.query.oid;
if (oid
&& oid.length > 0 && oid.length <= 32
&& oid.match(/^[a-z0-9]+$/i)) {
const sql = 'SELECT * FROM tSightings WHERE oid=?';
const rows = await db.query(sql, [oid]);
if (rows) {
status = 200;
data = {
'oid': oid,
'data': rows
};
} else {
status = 204;
}
} else {
status = 400;
}
} catch (e) {
console.error(e);
}
return { status, data };
}
async function postSighting(req) {
console.log("postSighting method entered")
let status = 500, data = null;
try {
const pic = req.body.pic;
const alive = req.body.alive;
const typeOfDeath = req.body.typeOfDeath;
const comment = req.body.comment;
const geoLocation = req.body.geoLocation;
//impliment appropriate checks here
if (1 == 1) {
const sql = 'INSERT INTO tSightings (pic, alive, typeOfDeath, comment, geoLocation) '
+ 'VALUES (?, ?, ?, ?, ?)';
const result = await db.query(sql, [pic, alive, typeOfDeath, comment, geoLocation]);
if (result.affectedRows) {
status = 201;
data = { 'id': result.insertId };
}
} else {
status = 400;
}
} catch (e) {
console.error(e);
}
return { status, data };
}
app.get('/', async (req, res) => {
console.log("express get submitted")
const { status, data } = await getSighting(req);
res.status(status);
if (data) res.json(data);
else res.end();
})
app.listen(port, () => {
console.log(`Running at http://localhost:${port}`)
})
app.get('/express_api', async (req, res) => {
console.log("express get submitted")
const { status, data } = await getData(req);
res.status(status);
if (data) res.json(data);
else res.end();
})
app.post('/', async (req, res) => {
const { status, data } = await postSighting(req);
res.status(status);
if (data) res.json(data);
else res.end();
})
app.put('/express_api', async (req, res) => {
res.status(405);
res.end();
})
app.delete('/express_api', async (req, res) => {
res.status(405);
res.end();
})
Front-end
A fetch() promise will reject with a TypeError when a network error is encountered or CORS is misconfigured on the server-side.
your're sending header content type = form-urlencoded and actual body as json
try {
const response = await fetch(url, {
method: 'POST',
//should be application json if your're stringifying it
headers: {'Content-Type':' 'application/json'},
body: jsonBody
});
await console.log(response);
// need to check if the response is valid or not
if(response.ok){
const jsonData = await response.json();
}else{
throw response
}
this.setState({
loading: false,
records: jsonData.records
});
}
Back-end
I don't know why your're setting custom headers while have use cors app.use(cors()); that allows all methods.
remove that
//was missing
app.use(bodyParser.json());
const corsOptions = {
origin: "*" // grant for all origins. can be use as per your ref url
}
app.use(cors(corsOptions));
// don't need this part
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', '*');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
next();
});
Related
I am using axios to make api calls using a proxy server with nodeJS as backend and reactJS as frontend.
node js file
const express = require('express');
const axios = require('axios').default;
const app = express();
require('dotenv').config();
const PORT = process.env.PORT || 8000;
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.get('/', (req, res) => {
res.redirect('/api')
})
// get anime on front page
app.get(`/api`, async (req, res) => {
try {
const response = await axios.get('https://api.jikan.moe/v4/anime');
const data = response.data
res.json(data.data)
}
catch (err) {
console.log(err.message)
}
})
// get anime by id
app.get('/api/anime/:id' ,async (req,res)=>{
try {
const id = req.params.id
const response = await axios.get(`https://api.jikan.moe/v4/anime/${id}`)
const data = response.data
res.json(data);
console.log(data)
}
catch (err) {
console.log(err)
}
})
app.listen(PORT, () => {
console.log('connected')
})
Here I am using Two routes, one for the main homepage to show all the data, and then one route to retrieve data by ID, but when i try to retrieve the data using ID it shows null in console.
import useFetch from "./usefetch";
import { useParams } from "react-router-dom";
import './style/animeDetails.css'
const AnimeDetails = () => {
const play = (e) => {
console.log(e.target)
}
const {id} = useParams()
const { data: animeDet, isLoading, error } = useFetch('/api/anime/' + id);
console.log(animeDet.data)
return (
<div className="details">
</div>
);
}
export default AnimeDetails;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Here i am making a call to the proxy server to retrieve the data by ID.
try to check isLoading first, like:
const { data: animeDet, isLoading, error } = useFetch('/api/anime/' + id);
if (isLoading) {
return null
}
console.log(animeDet.data)
return (
<div className="details">
</div>
);
I'm trying to follow the Stripe Checkout subscription instructions:
https://stripe.com/docs/billing/subscriptions/build-subscriptions?ui=checkout
When I submit the form, over localhost I get "Cannot POST /create-checkout-session" (404 in network tab), and if I run from my production server, it just opens /create-checkout-session as a new (blank) Vue page. I have tried changing the form action to https://mydomain.xyz/create-checkout-session, but it didn't work.
Subscribe.vue
<form action="/create-checkout-session" method="POST">
<input type="hidden" name="priceId" value="[removed for Stack Overflow]" />
<button type="submit">Checkout</button>
</form>
I don't know if something is interfering with the endpoint, so I've copied my entire app.js file:
app.js
let express = require('express'),
cors = require('cors'),
mongoose = require('mongoose'),
database = require('./database'),
bodyParser = require('body-parser');
// Set your secret key. Remember to switch to your live secret key in production.
// See your keys here: https://dashboard.stripe.com/apikeys
const stripe = require('stripe')('[removed for StackOverflow]');
//connect mongoDB
mongoose.Promise = global.Promise;
mongoose.connect(database.db, {
useNewUrlParser: true,
useUnifiedTopology: true
}).then(() => {
console.log("Database connected")
},
error => {
console.log("Database couldn't be connected to: " + error);
}
)
const cryptoEndPoint = require('../backend/routes/crypto.route')
const app = express();
app.use(decodeIDToken);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(cors())
//API
app.use('/api', cryptoEndPoint)
app.post("/create-checkout-session", async (req, res) => {
console.log("can't even get anything to console log, only get createError is not defined");
const { priceId } = req.body;
// Create new Checkout Session for the order
// Other optional params include:
// [billing_address_collection] - to display billing address details on the page
// [customer] - if you have an existing Stripe Customer ID
// [customer_email] - lets you prefill the email input in the form
// [automatic_tax] - to automatically calculate sales tax, VAT and GST in the checkout page
// For full details see https://stripe.com/docs/api/checkout/sessions/create
try {
const session = await stripe.checkout.sessions.create({
mode: 'subscription',
line_items: [
{
price: priceId,
// For metered billing, do not pass quantity
quantity: 1,
},
],
// {CHECKOUT_SESSION_ID} is a string literal; do not change it!
// the actual Session ID is returned in the query parameter when your customer
// is redirected to the success page.
success_url: 'https://mydomain.xyz/thankyou?session_id={CHECKOUT_SESSION_ID}',
cancel_url: 'https://mydomain.xyz/thankyou',
});
return res.redirect(303, session.url);
} catch (e) {
res.status(400);
return res.send({
error: {
message: e.message,
}
});
}
});
//create port
const port = process.env.PORT || 4000;
const server = app.listen(port, () => {
console.log('Connected to port ' + port);
})
//Find 404
app.use((req, res, next) => {
next(createError(404));
})
//error handler
app.use(function (err, req, res, next) {
console.log(err.message);
if (!err.statusCode) err.statusCode = 500;
res.status(err.statusCode).send(err.message);
})
/**
* Decodes the JSON Web Token sent via the frontend app
* Makes the currentUser (firebase) data available on the body.
*/
async function decodeIDToken(req, res, next) {
if (req.headers?.authorization?.startsWith('Bearer ')) {
const idToken = req.headers.authorization.split('Bearer ')[1];
// console.log(idToken);
try {
const decodedToken = await admin.auth().verifyIdToken(idToken);
// console.log("one");
req['currentUser'] = decodedToken;
// console.log("two");
} catch (err) {
console.log("error: " + err);
}
}
next();
}
app.post("/webhook", async (req, res) => {
let data;
let eventType;
// Check if webhook signing is configured.
const webhookSecret = '[removed for Stack Overflow]'
if (webhookSecret) {
// Retrieve the event by verifying the signature using the raw body and secret.
let event;
let signature = req.headers["stripe-signature"];
try {
event = stripe.webhooks.constructEvent(
req.body,
signature,
webhookSecret
);
} catch (err) {
console.log(`⚠️ Webhook signature verification failed.`);
return res.sendStatus(400);
}
// Extract the object from the event.
data = event.data;
eventType = event.type;
} else {
// Webhook signing is recommended, but if the secret is not configured in `config.js`,
// retrieve the event data directly from the request body.
data = req.body.data;
eventType = req.body.type;
}
switch (eventType) {
case 'checkout.session.completed':
//...
break;
case 'invoice.paid':
//...
break;
case 'invoice.payment_failed':
//...
break;
default:
// Unhandled event type
}
res.sendStatus(200);
});
Does anyone know what is going wrong?
I added this to my app.js file, and it's working:
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', "*");
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
}
app.use(allowCrossDomain);
I need to make unit tests for some post requests but i dont understand how.I tried with mswjs but the test passes because i'm missing something and i dont know what.I tried to test the requests in an usual way but i wasnt able to put my conditions there and it was sending only 200 status code..
To start with,this is my folder structure:
+main folder
++nodeServer
+++public
+++routes
++public
++src
+++tests
This is my try for testing the post request to /subscribe endpoint,where i should send an email as a payload and get the response that the payload was received succesefully.
subscribeFetch.test.js:
import {setupServer} from 'msw/node'
import {rest} from 'msw'
const handlers = [
rest.post("/api/subscribe",(req,res,context)=>{
if (!req.body || !req.body.email) {
return res(context.status(400).json({ error: "Wrong payload" }));
}
if (req.body.email === 'forbidden#email.com') {
return res(context.status(422).json({ error: "Email is already in use" }));
}
return res(
context.status(200),
context.json({email:'gigi#gmail.com'})
)
})
]
const server = setupServer(...handlers)
beforeAll(()=>server.listen())
afterAll(()=>server.close())
afterEach(()=>server.resetHandlers())
test('should send post request to the server',async()=>{
server.use(
rest.post('/api/subscribe',(req,res,ctx)=>{
return res(
expect (ctx.status()).toBe(200)
)
}
)
)
})
//export {handlers,rest}
This is the subscribe post request function that i need to test:
import { validateEmail } from './email-validator.js'
export const sendSubscribe = (emailInput) => {
const isValidEmail = validateEmail(emailInput)
if (isValidEmail === true) {
sendData(emailInput)
}
}
export const sendHttpRequest = (method, url, data) => {
return fetch(url, {
method: method,
body: JSON.stringify(data),
headers: data
? {
'Content-Type': 'application/json'
}
: {}
}).then(response => {
if (response.status >= 400) {
return response.json().then(errResData => {
const error = new Error('Something went wrong!')
error.data = errResData
throw error
})
}
return response.json()
})
}
const sendData = (emailInput) => {
sendHttpRequest('POST', '/api/subscribe', {
email: emailInput
}).then(responseData => {
return responseData
}).catch(err => {
console.log(err, err.data)
window.alert(err.data.error)
})
}
Files from the server:
app.js:
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const indexRouter = require('./routes/index');
const communityRouter = require('./routes/community');
const analyticsRouter = require('./routes/analytics');
const app = express();
global.appRoot = path.resolve(__dirname);
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/community', communityRouter);
app.use('/analytics', analyticsRouter);
module.exports = app;
index.js from routes folder in the server folder:
const express = require('express');
const router = express.Router();
const FileStorage = require('../services/FileStorage');
/* POST /subscribe */
router.post('/subscribe', async function (req, res) {
try {
if (!req.body || !req.body.email) {
return res.status(400).json({ error: "Wrong payload" });
}
if (req.body.email === 'forbidden#email.com') {
return res.status(422).json({ error: "Email is already in use" });
}
const data = {email: req.body.email};
await FileStorage.writeFile('user.json', data);
await res.json({success: true})
} catch (e) {
console.log(e);
res.status(500).send('Internal error');
}
});
/* GET /unsubscribe */
router.post('/unsubscribe', async function (req, res) {
try {
await FileStorage.deleteFile('user.json');
await FileStorage.writeFile('user-analytics.json', []);
await FileStorage.writeFile('performance-analytics.json', []);
await res.json({success: true})
} catch (e) {
console.log(e);
res.status(500).send('Internal error');
}
});
module.exports = router;
Please guys,help me write unit test for subscribe endpoint to match the conditions from index.js file from routes folder in the server folder,thank you in advance!
So,i got the expected result without any library,but i dont know if its a good aproach,but at least it works :
const app = require('../../../personal-website-server/app')
const request = require('supertest')
describe('POST /subscribe', () => {
it('should give 400 status code when email is empty', async () => {
const email = { email: '' }
const response = await request(app).post('/subscribe').send(email)
if (!request.body || !request.body.email) {
expect(response.status).toBe(400)
}
})
it('should give 422 status code when email is forbidden', async () => {
const email = { email: 'forbidden#gmail.com' }
const response = await request(app).post('/subscribe').send(email)
if (request.body === 'forbidden#gmail.com') {
expect(response.status).toBe(422)
}
})
it('should give 200 status code when email is valid', async () => {
const email = { email: 'gigi#gmail.com' }
const response = await request(app).post('/subscribe').send(email)
expect(response.error).toBe(false)
expect(response.status).toBe(200)
expect(response.body.body).not.toBeNull()
})
})
I made an api app in Node Express. Routes post and put are working perfectly. Delete route is also working but I dont see confirmation of resolved promise, instead after few secs I see those errors
Access to XMLHttpRequest at 'https://ahi' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
PageAdmin.js:179 fail Error: Network Error
DELETE https://ahi net::ERR_FAILED
I was already dealing with that problem at beginning of setting up app on server so I searched how to deal with it. Here is my middleware code on server for setting up headers
function setHeaders(app) {
app.use(function (req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Methods",
"GET, POST, OPTIONS, PUT, PATCH, DELETE"
);
res.setHeader(
"Access-Control-Allow-Headers",
"Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Allow-Origin, Access-Control-Allow-Methods, x-auth-token"
);
res.setHeader("Access-Control-Allow-Credentials", true);
// handle OPTIONS method
if ("OPTIONS" == req.method) {
return res.sendStatus(200);
} else {
next();
}
});
}
Here is the code for routes
const express = require("express");
const router = express.Router();
const mongoose = require("mongoose");
const auth = require("../middleware/auth");
const { ProgrammingTool, validate } = require("../models/programmingTool");
const msg400 = "Bad request";
const msg400InData = "Item already exists in database";
const msg404 = "Could not find item in database";
const msg500 = "Something went wrong";
router.get("/", async (req, res) => {
try {
const tools = await ProgrammingTool.find();
res.send(tools);
} catch (e) {
console.log("failed getting tools", e);
res.status(500).send(msg500);
}
});
router.get("/:id", async (req, res) => {
if (!mongoose.Types.ObjectId.isValid(req.params.id))
return res.status(404).send(msg404);
const tool = await ProgrammingTool.findById(req.params.id);
if (!tool) return res.status(404).send(msg404);
res.send(tool);
});
router.post("/", auth, async (req, res) => {
const validation = validate(req.body);
if (validation.error) return res.status(400).send(msg400);
try {
const toolInData = await ProgrammingTool.findOne({ name: req.body.name });
if (toolInData) return res.status(400).send(msg400InData);
} catch (e) {
return res.status(500).send(msg500);
}
const tool = new ProgrammingTool({ name: req.body.name });
try {
await tool.validate();
} catch (e) {
console.log("did not pass mongoose validation at posting", e);
return res.status(400).send(msg400);
}
try {
const result = await tool.save();
res.send(result);
} catch (e) {
console.log("failed to post tool");
res.status(500).send(msg500);
}
});
router.delete("/:id", auth, async (req, res) => {
const id = req.params.id;
let tool;
try {
tool = await ProgrammingTool.findById(id);
} catch (e) {
console.log("could not find the tool with provided id", e);
res.status(404).send(msg404);
}
try {
await tool.delete();
} catch (e) {
console.log("failed deleting tool", e);
res.status(500).send(msg500);
}
});
router.put("/:id", auth, async (req, res) => {
const validation = validate(req.body);
if (validation.error) return res.status(400).send(msg400);
const id = req.params.id;
const tool = await ProgrammingTool.findById(id);
if (!tool) res.status(404).send(msg404);
tool.name = req.body.name;
try {
await tool.validate();
} catch (e) {
console.log("did not pass mongoose validation at putting", e);
return res.status(400).send(msg400);
}
try {
const result = await tool.save();
res.send(result);
} catch (e) {
console.log("failed to save edited tool");
res.status(500).send(msg500);
}
});
router.delete("/", auth, (req, res) => {
res.status(400).send(msg400);
});
router.put("/", auth, (req, res) => {
res.status(400).send(msg400);
});
What really suprises me is that the error is getting thrown but route does it job, item is deleted from database.
In the delete route there are 2 problems.
you are not using return so even after the first error it goes to the second try catch block. Add return to both res.status(..).send(..)
For a successful Delete operation you are not returning a 2xx status code. So if there is a successful deletion the request will be stuck cause you are not returning anything, after some time probably it will time out.
I'm trying to show some information about a user in front-end, but I don't know why is not showing anything. If I access the server using localhost:8080/api/user I can see the information in an empty page (is just a dummy database that I had), but I can't print them in my content page, my code recognizes the list as being empty.
I'm a beginner and I just started using React, Node.js, and Express.
UserStatus.js
import React from 'react';
class UserStatus extends React.Component {
constructor(props){
super(props);
this.state = {
list: []
}
}
// Fetch the list on first mount
componentDidMount() {
}
// Retrieves the list of items from the Express app
getList = () => {
fetch('/api/user')
.then(res => res.json())
.then(list => this.setState({ list })
)
}
render() {
const { list } = this.state;
return (
<div className="App">
<h1>User Status</h1>
{/* Check to see if any items are found*/}
{list.length ? (
<div>
{/* Render the list of items */}
{list.map((item) => {
return(
<div>
{item}
</div>
);
})}
</div>
) : (
<div>
<h2>No List Users Found</h2>
</div>
)
}
</div>
);
}
}
export default UserStatus
server.js
//Initiallising node modules
var express = require("express");
var bodyParser = require("body-parser");
var sql = require("mssql");
var app = express();
// Body Parser Middleware
app.use(bodyParser.json());
//CORS Middleware
app.use(function (req, res, next) {
//Enabling CORS
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, contentType,Content-Type, Accept, Authorization");
next();
});
//Setting up server
var server = app.listen(process.env.PORT || 8080, function () {
var port = server.address().port;
console.log("App now running on port", port);
});
//Initiallising connection string
var dbConfig = {
user: '---',
password: '---',
server: '----',
database: '---'
};
//Function to connect to database and execute query
var executeQuery = function (query, res) {
sql.connect(dbConfig, function (err) {
if (err) {
console.log("Error while connecting database :- " + err);
res.send(err);
} else {
// create Request object
var request = new sql.Request();
// query to the database
request.query(query, function (err, ress) {
if (err) {
console.log("Error while querying database :- " + err);
res.send(err);
} else {
res.json(ress);
}
});
}
});
}
//GET API
app.get("/api/user", function (req, res) {
var query = "select * from Machine";
executeQuery(query, res);
});
//POST API
app.post("/api/user", function (req, res) {
var query = "INSERT INTO [user] (Name,Email,Password) VALUES (req.body.Name,req.body.Email,req.body.Password)";
executeQuery(res, query);
});
//PUT API
app.put("/api/user/:id", function (req, res) {
var query = "UPDATE [user] SET Name= " + req.body.Name + " , Email= " + req.body.Email + " WHERE Id= " + req.params.id;
executeQuery(res, query);
});
// DELETE API
app.delete("/api/user /:id", function (req, res) {
var query = "DELETE FROM [user] WHERE Id=" + req.params.id;
executeQuery(res, query);
});
To debug you can set breakpoints or use console.log or some other console method. First you can check your fetch response:
getList = () => {
fetch('/api/user')
.then(res => {
console.log(res) // is it a string or is it already json? What is the data structure?
return res.json()
})
.then(list => this.setState({ list }))
.catch(err => console.error(err)) // you should handle errors
}
Also you should catch errors. It seems to me you are returning a dataset with a toplevel 'recordset' attribute. So you probably have to do: return res.json().recordset
First of all, list.length is just a number you need to check if the array is greater than zero
list.length > 0
Secondly, Check to see if the data is being received from the backend
getList = async () => {
try{
let res = await fetch('/api/user');
console.log(res);
} catch (err) {
console.log(err);
}
}