Fetch request not fetching backend object - nextjs and express - node.js

I have a Nextjs frontend trying to make a fetch request to my node and express backend but it's not happening for some reason. I'm trying to access this object in the backend: {"data": ["data1", "data2", "data3"]} but I'm not able to even fetch it. Here is my backend code:
const express = require('express')
const app = express()
app.get("/api", (req, res) => {
res.json({"data": ["data1", "data2", "data3"]})
})
app.listen(5000, () => { console.log("Server started on port 5000") })
Here is my next.js file trying to make this request:
import React, { Component, useEffect, useState } from 'react';
const Product = () => {
const [backendData, setBackendData] = useState([{}])
useEffect(() => {
fetch("/api").then(
response => response.json()
).then(
data => {
setBackendData(data)
}
)
}, [])
return (
<div>
{(typeof backendData.data === 'undefined') ? (
<p>Loading...</p>
) : (
backendData.data.map((data, i) => (
<p key={i}>{data}</p>
))
)}
</div>
);
}
export default Product
I've included this line in my package.json file "proxy": "http://localhost:5000", so it should be going to that link and when I search http://localhost:5000 in my browser, I get the object that I've written in the backend like this: {"data":["data1","data2","data3"]}.
When I click on Network when I hit inspect on the page, the fetch request doesn't show up either.
Does anyone know why I'm unable to fetch this object in nextjs?

Related

Axios Problems (uncaught in promise) using zustand

Hi there i have problems with making the api call to my server. Using Postman i receive correctly my data from the URL but when i come into react and i use Axios to get those data i have the Axios error Uncaught in promise status code: 300 Here my code.
import {create} from 'zustand'
import axios from 'axios'
const URL1 = "http://localhost:5000/livespa"
export const useStore = create((set, get) => ({
liveSpa:[],
loadLivespa: async () => {
const response = await axios.get(URL1)
set({ liveSpa: await response.data})
},
}))
And my frontend page is like
const LiveSpa = () => {
const data = useStore((state) => state.liveSpa)
const loadBets = useStore((state)=> state.loadLivespa)
useEffect(() => {
loadBets()
}, [])
return (...)
}
I tried using Fetch but same problems, debugging my node server but it works fine using Postman

Using promise, resolve and axios and get multiple same returns each time GET [duplicate]

This question already has answers here:
How to call loading function with React useEffect only once
(15 answers)
Closed 3 months ago.
I am currently learning nodejs and react, and I want to achieve data transmission between frontend and backend. During this, I found that every time I refresh the website, the console in the browser would print out the content several times.
Here is my frontend code for post, get data and display data result.
callAPI.js
import axios from 'axios'
const api = 'http://localhost:5000'
class callAPI{
getSomething(){
return new Promise((resolve)=>resolve(axios.get(`${api}`)))
}
sendSomething(body){
return new Promise((resolve)=>resolve(axios.post(`${api}/hello`,body)))
}
}
export default new callAPI()`
Page.js
import React, { useState } from 'react'
import callAPI from './callAPI';
export default function Page(){
const[content, setContent] = useState("")
const[greeting, setGreeting] = useState("")
function getContent(){
callAPI.getSomething().then(response=>{
console.log(response.data)
setContent(response.data)
})
}
function handleLB(){
callAPI.sendSomething({name:"Sam"})
.then((response)=>{
console.log(response.data)
setGreeting(response.data)
})
}
function handleCC(){
callAPI.sendSomething({name:"Mary"})
.then((response)=>{
console.log(response.data)
setGreeting(response.data)
})
}
getContent()
console.log(content)
return(
<>
<h1>{content}</h1>
<div>
<button onClick={handleLB}>Sam is comming</button>
<button onClick={handleCC}>Mary is comming</button>
</div>
<div>
<p>{greeting}</p>
</div>
</>
)
}
Here is my backend code
app.js
var express = require('express');
var cors = require('cors')
var app = express();
const greeting={"Sam":"Handsome boy","Mary":"Young and beautiful lady"}
var corsOptions={
credentiala:true,
origin:'http://localhost:3000',
optionsSuccessStatus:200
}
app.use(cors(corsOptions))
app.use(express.urlencoded({extended:true}));
app.use(express.json());
app.get('/',function(req, res) {
res.send('Knock knock, who\'s coming?')
})
app.post('/hello',function(req, res){
//console.log(req.body.name)
let grt = greeting[req.body.name]
res.send(grt)
})
app.listen(5000,function(){
console.log('App is listening on port 5000...')
})
And here is a picture of my browser console
In my understanding, each GET/POST should only have one return results. In this case, when I POST something, I only get one return results. But for GET, I get multiple. And I'm really curious why this would happen.
First of all axios return promise by itself so don't need to put again in Promises and call getContent using useEffect.
useEffect(() => {
getContent()
},[])
In dependency array you can have some dependency or leave it blank(so it will call the getContent only once time)

Image upload from React to NodeJS, port connection refused

Hello Dear Community :)
I'm trying to code an image upload on my website, from React to Backend in NodeJS.
I have this error with this port connection.
This path http://localhost:5000/api/plants with post method works fine in PostMan (with uploading picture). The problem occurs when I want to upload to the backend server.
Here is the problem logged in the console
xhr.js:177 POST http://localhost:5000/api/plants
net::ERR_CONNECTION_REFUSED
Here is my code :
import React, { Component, useState } from "react";
import axios from 'axios';
class UploadImg extends Component {
state = {
image: null,
}
handleChange = event => {
this.setState({
image: event.target.files[0],
loaded: 0,
})
}
handleFileUpload = event => {
console.log('the new file upload is :', event.target.files[0]);
}
onClickHandler = (event) => {
const data = new FormData()
data.append('file', this.state.image)
axios.post('http://localhost:5000/api/plants', data)
.then(res => {
console.log(res)
})
.catch((error) => {
console.log(error)
})
event.preventDefault();
}
render() {
return (
<div>
<h2>New Thing</h2>
<form onSubmit={this.handleSubmit}>
<input type="file" onChange={this.handleFileUpload} />
<button onClick={this.onClickHandler} type="submit">Upload</button>
</form>
</div>
)
}
}
export default UploadImg
This link might help you: https://www.digitalocean.com/community/questions/why-can-i-call-api-port-from-react-app-using-ip-address-but-not-when-i-use-localhost
TL;DR: replace localhost in the axios request to whatever your machine's IP address is.

Posting data from EJS to Node.js

I have an index.html EJS rendered by a koa/Node.js app which contains a javascript snippet to post data about the current page to the same app, to an endpoint to save in a database.
The javascript code ( an AJAX fetch POST) reaches the Node.js endpoint but doesn't transmit any data. I don't see any typo in the code.
[CORRECTION] indeed a typo with the bodyparser
# index.js
const Koa = require("koa");
const path = require("path");
const render = require("koa-ejs");
const bodyParser = require("koa-bodyparser");
const router = require("./routes/routes.js");
const app = new Koa();
render(app, {
root: path.join(__dirname, "/views"),
layout: false,
viewExt: "html",
});
app
.use(bodyParser())
.use(router.routes())
.use(router.allowedMethods())
.use(staticCache("./images", { maxAge: 600000 }))
.listen(PORT, () => {
console.log(`Running on port ${PORT}`);
});
In the index.html, I have a button that triggers a POST request to an endpoint (/node/insert) of the koaRouter. The action is to save information about the current page (say, document.location.href) in a Postgres database.
# /views/index.html
[...]
<form id="newRow">
<input type="submit" value="New row">
</form>
[...]
<script type="module" src="fetch.js" async></script>
where:
# /views/fetch.js
const data = {
app: "Node",
url: document.location.href,
...
};
document.getElementById("newRow").addEventListener("submit", (e) => {
e.preventDefault();
fetch("/node/insert", {
method: "POST",
headers: {
"Content-Type": "application/json; charset-UTF-8",
},
body: JSON.stringify(data),
})
.then((res) => {
if (res.ok) {
return res.json();
}
return Promise.reject(res);
})
.then((res) => console.log("front", res))
.catch((err) => console.warn(err));
Among the routes, I defined an endpoint /node/insert to respond to this action:
# routes.js
const koaRouter = require("koa-router");
const router = new koaRouter();
router.post("/node/insert", async (ctx) => {
console.log("posted", ctx.request.body);
^^^ "posted" is positively printed in terminal after submit
if (ctx.request.body) {
return (ctx.response.status = 200)
} else {
return (ctx.response.status = 404); <-- check
}
})
The endpoint "/node/insert" is reached since I can console.log positively, but the body isn't passed to the endpoint: ctx.request.body = {}. I have the following error:
"SyntaxError: Unexpected token O in JSON at position 0"
detected from fetch.js (probably because the body is {}?).
I don't see what is wrong.
Note: the Node app runs in a container (pm2-runtime start index.js) and use Nginx as reverse proxy, static files server and load-balancer`
Try:
const koaJson = require(koa-json);
app.use(koaJson());
Just a typo in the bodyparser as Evert pointed and bad positioning of the middleware
curl --data "app=Node" HTTP://localhost:8000/node responds normaly.

ReactJS download file from Express Server

I'm trying to make my user able to download a file from our backend server. I've tried the solution from this question as well as the backend from this.
Sadly none of them worked. The download itself works through postman, but not in react.
Additional info: The Backend is running on the same machine but on port 3001 while the frontend is running on port 3000
I'm not sure if that helps, but the react frontend is connected to the backend via proxy in the package.json
"proxy": "http://localhost:3001",
The client side currently looks like this:
const download = require("downloadjs");
const handleDownload = async () => {
const res = await fetch("http://localhost:3001/download");
const blob = await res.blob();
download(blob, "test.pdf");
}
function App() {
return (
<div className="App">
<header className="App-header">
<button onClick={() => handleDownload().finally(() => console.log("Passed through the whole handleDownload Request"))}> </button>
</header>
</div>
);
}
while on the backend side I'm using this code as from the previous questions asked here on stackoverflow.
app.get('/getdoc', function (req, res) {
res.download(path.join(__dirname, 'files/test.pdf'), function (err) {
console.log(err);
});
});
This is the Code working through Postman, but it won't trigger a download in React.
The Error occurring in react looks like this:
App.js:8 GET http://localhost:3001/download/test.pdf net::ERR_CONNECTION_REFUSED
Uncaught (in promise) TypeError: Failed to fetch
So it seems the handling on frontend seems to be the problem, as it is not triggering the Save Dialog from the browser (Chrome).
Your request to postman will work because I assume you are hitting the correct endpoint which is '/getdoc' which will let you download the pdf via postman.
However, your fetch request does not seem to match the API endpoint that serves the pdf document. That is why your React Component will give you the error on download.
const handleDownload = async () => {
const res = await fetch("http://localhost:3001/download");
const blob = await res.blob();
download(blob, "test.pdf");
}
//the fetch call for "http://localhost:3001/download" will not hit '/getdoc'
app.get('/getdoc', function (req, res) {
res.download(path.join(__dirname, 'files/test.pdf'), function (err) {
console.log(err);
});
});
Here is how I implemented the pdf download.
//resume route... this route is hit when you make a GET request to /api/resume
const router = require('express').Router();
module.exports = router;
//when route is hit the resume is downloaded
//aka /api/resume
router.get('/', (req, res, next) => {
try {
const file = `${__dirname}/resume/resume.pdf`;
res.download(file);
console.log('here');
} catch (err) {
console.log(err);
}
});
//react component
import React from 'react';
import download from 'downloadjs';
const Resume = () => {
return (
<div>
<button
type="button"
onClick={async () => {
const res = await fetch('/api/resume');
const blob = await res.blob();
download(blob, 'test.pdf');
}}
>
Download
</button>
</div>
);
};
Try this:
const handleDownload = () => {
var reqObj = new XMLHttpRequest();
reqObj.open('GET','http://localhost:3001/download',true); // 'getpdf' is the URI to recongize your request at the server
reqObj.send();
reqObj.onreadystatechange = function() {
var resObj = this;
if(resObj.readyState == resObj.DONE) {
if (resObj.status != 200) {
console.log(200);
} else if (resObj.status == 200){
var resTxt = reqObj.responseText;
window.location.assign(resTxt); // Opens the pdf download prompt
}
}
}

Resources