React Fetch to Node Server in Herokuapp - node.js

I'm attempting to fetch data from my node.js server (which is on port 7000) through react in heroku with this code:
const { name } = e.target.elements;
let details = {
name: name.value,
};
let response = await fetch("/post", {
method: "POST",
headers: {
"Content-Type": "application/json;charset=utf-8",
},
body: JSON.stringify(details),
});
and this server setup:
if(process.env.NODE_ENV === "production") {
app.use(express.static('../client/build'));
app.get('*', (req, res) => {
req.sendFile(path.resolve('client/build/index.html', { root: "../" }));
});
}
app.post("/post", async (req, res) => {
const queryRes = await searchFromQuery(req.body.name);
res.json({
status: queryRes.isFound ? "found" : "notFound", teaminfo: {
name: queryRes.name,
number: queryRes.number,
avgScore: queryRes.avgScore,
predictedScore: queryRes.predictedScore,
}
});
});
app.listen(PORT, console.log(`Server started on port ${PORT}`));
app.get("/", function(req, res) {
res.sendFile('client/build/index.html', { root: "../" });
});
However, when I print out req there doesn't seem to be any data related to the react request. I believe it has to do with my express setup (which I set to express.static() for heroku, though it was initially express.json())
Additionally, the proxy in my package.json is still set to http://localhost:7000.

Issue resolved by adding app.use(express.json()) back to the server file alongside static.

Related

Save JSON file to local folder on client with Nextjs/ NodeJs and Firebase hosting/functions

I'm using NextJS for my application and i would like to write an JSON-file to the client in a function. On my localhost everything works fine and without any problem, but the application gets build and deployed to firebase it isn't working anymore.
I already tried multiple things, i already created the function in the api folder of NextJs and also created an localhost node server and call them in nextjs API as:
var fs = require('fs').promises;
export default function (req, res) {
console.log(JSON.stringify(req.body))
let Data= JSON.stringify(req.body)
fetch('http://localhost:9091/data', {
method: 'POST',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
body: Data
})
.then((response) => {
console.log('here')
return response.json(); // or .text() or .blob() ...
})
.then((text) => {
console.log(text)
res.status(200)
// text is the response body
})
.catch((e) => {
// error in e.message
});
As said this works when the application runs on localhost but not on firebase hosting/functions.
The node server looks like:
var express = require('express');
var app = express();
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
var fs = require('fs').promises;
app.get('/', function (req, res) {
res.send('Hello World');
})
app.post('/data', function (req, res) {
res.send('Hello World');
let Order = req.body;
console.log(Order)
fs.readFile("object.json",'utf8').then(data =>{
let json = JSON.parse(data);
json.push(Order);
fs.writeFile("object.json", JSON.stringify(json)).then( () => { console.log('Append Success'); })
.catch(err => { console.log("Append Failed: " + err);});
})
})
var server = app.listen(9091, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
})
What I'm trying to achieve is that data is appended to the JSON file and stored locally on the client.
Does anyone have an idea how to handle this properly?

How to fix/troubleshoot React Express 404 Error with static site?

I have an input that calls this submit function onSubmit:
const onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
setfruit(item);
console.log("sent")
fetch('/api/tasks/add', {
method: 'post',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ Name: item.Name,Quantity: item.Quantity, edit: item.edit }),
}).then(() => {
setItem(itemd)
getTasks();
});
};
and my route:
router.post('/add', (req, res) => {
const { Name, Price, edit } = req.body;
const newTask = new Task({ Name, Price, edit });
newTask.save()
.then(task => res.json(task))
.catch(err => res.json(500, err));
});
Heres my index.js:
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const app = express();
const routeTasks = require('./src/routes/tasks');
app.use(express.static(path.join(__dirname, './client/build')));
app.use(bodyParser.json());
app.use('/api/tasks', routeTasks, (req, res) => res.sendStatus(401));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname + './client/build/index.html'));
});
const port = 5000;
app.listen(port);
console.log(`listening on ${port}`);
Every time I call the onSubmit function, I get a 404 error. I can't tell why.
I used this repo as a guide for creating my express server but for some reason when I switch the underlying React app it stops working.
https://github.com/jmsv/simple-mern
Per Phil's comment, my issue was that the example Repo I was going off of used a React proxy which I hadn't configured in my own app. Once I added that to the package.json file, it worked.

Next.js dynamic route - 404 on page reload after added SLUG

I'm used Next.js and Node.js for my project.
What we have:
Pages structure:
pages/products/PageSomeName.js
pages/products/PageEnotherName.js
pages/products/PageName.js
Pages name in products folder is can be different
routes.js
routes.add("/products/:id", "/products/[id].js");
server.js
app.prepare().then(() => {
const server = express();
server.use(
"./images",
express.static(path.join(__dirname, "images"), {
maxAge: dev ? "0" : "365d"
})
);
server.use(bodyParser.json());
server.get("*", (req, res) => {
return handle(req, res);
});
const PORT = process.env.PORT || 9001;
server.listen(PORT, err => {
if (err) throw err;
console.log(`> Read on http://${process.env.SITE_URL_FULL}`);
});
});
Link component
<Link href={`/products/${data.link}`} as={`/products/${data.slug}`}/>
data array
export const storeProducts = [
{
id: 1,
title: "Title1",
link: "product_name_some",
slug: "product-1-slug",
},
{
id: 2,
title: "Title2",
link: "product_name_different_some_name",
slug: "product-2-slug"
},
There was a problem when I added slug for my links.
By client side everything works fine. I take localhost:3000/product-2-slug in browser url. But after reload, I take 404 error page from Next.js
What I must added by server side in server.js for normal server reloading?
Maybe I need change Link component or next-route settings in routes.js
Thanks!
In server.js you should have a routes as below.
server.get("/products/product1", (req, res) => {
return handle(req, res);
});
server.get("/products/product2", (req, res) => {
return handle(req, res);
});
server.get("/products/product3", (req, res) => {
return handle(req, res);
});
A good way to handle the same is to create a generic products.js inside the pages directory and on server handle as below.
server.js
server.get("/products/:id", (req, res) => {
return handle(req, res, { id: req.params.id });
});
and in
pages/products.js we can create a getInitialProps method
static getInitialProps (context) {
// parameters reqturned from server are accessible via
const id = ctx.query.id
}

express.json() doens't work on production

I have a NodeJS and React project. I am having a problem. I didnt understand what the problems are. First I want to show you what my problem is.
on localhost. I want like this on heroku but it returns me as the next one
My problem's photo:
As you see on the photo there is an html file in my user object on Heroku deployment.
But when I start my project on localhost the user has an object that is coming from my mongo database. Express.json() is catching and working correctly on localhost but it doesnt work on Heroku. Why does it happen? What is my problem?
Here is my server.js file :
const express = require("express");
const path = require("path");
const app = express();
const connectDB = require("./config/db");
const PORT = process.env.PORT || 5000;
connectDB();
app.use(express.json());
app.use(express.json({ extended: false }));
app.use(express.static("client/build"));
if (process.env.NODE_ENV === "production") {
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, "client", "build", "index.html"));
});
}
app.use("/", require("./routes/quizRoute"));
app.use("/users", require("./routes/userRoute"));
app.use("/auth", require("./routes/authRoute"));
app.listen(PORT, () => {
console.log("Server is started on the port " + PORT);
});
Client Side request
//SET AUTH WORK
import axios from "axios";
const setAuthToken = token => {
if (token) {
axios.defaults.headers.common["x-auth-token"] = token;
} else {
delete axios.dafaults.header.common["x-auth-token"];
}
};
export default setAuthToken;
//LOAD USER
const loadUser = async () => {
if (localStorage.token) {
setAuthToken(localStorage.token);
}
try {
const res = await axios.get("/auth");
dispatch({ type: USER_LOADED, payload: res.data });
} catch (err) {
dispatch({
type: AUTH_ERROR,
payload:
"AUTH_ERROR: Token dogrulanamadi veya /auth'a GET isteginde bir sorun var"
});
}
};
enter code here
Why you are having the issue:  
I believe your bundler sets the NODE_ENV value to production when it builds for the deploy environments i.e Heroku. So you are having this issue because of the catch-all route that sends back your client index.html on every get request:
if (process.env.NODE_ENV === "production") {
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, "client", "build", "index.html"));
});
}
Consequently, when you make the get request to the /auth route from your client app, the request gets intercepted by this catch-all route handler before getting to the expected route handler. I'm pretty certain you would get back that HTML string whenever you make any get request to your server, not just the for /auth
The solution:  
The easy fix for this would be for you to move the catch-all route below your API routes like this:
app.use("/", require("./routes/quizRoute"));
app.use("/users", require("./routes/userRoute"));
app.use("/auth", require("./routes/authRoute"));
// Every other API or similar routes should be before this catch-all
if (process.env.NODE_ENV === "production") {
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, "client", "build", "index.html"));
});
}

NextJS and React: Cannot read property 'email' of undefined

I try to send data from my client to my server. For that, i use React with NextJS, because you have the server and client-side in one app.
I use the following handleSubmitFunction:
handleSubmit() {
const email = this.state.email;
fetch('/', {
method: 'POST',
body: email,
});
}
and this is my server.js file in the located in / at my project
const express = require('express')
const next = require('next')
const bodyParser = require('body-parser')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare()
.then(() => {
const server = express()
//parse application
server.use(bodyParser.urlencoded({ extended: false}))
//parse application/json
server.use(bodyParser.json())
server.post('/', (req, res) => {
console.log(req.body.email);
res.end("success!");
})
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(3000, (err) => {
if (err) throw err
console.log('> Ready on http://localhost:3000')
})
})
.catch((ex) => {
console.error(ex.stack)
process.exit(1)
})
When the handleSubmit Function is running, i get the following Output from the Server Console:
Cannot read property 'email' of undefined
Where exactly is my mistake?
I have little experience in node JS environments. I would be very grateful if you could show me concrete solutions. Thank you for your replies.
It seems you have to parse header and JSON.stringify the email.
fetch('/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({email:email}),
}).then((res)=> console.log('Worked'))

Resources