NextJS and React: Cannot read property 'email' of undefined - node.js

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'))

Related

XHR POST 404 error when using fetch api with NodeJS and Express

I am currently learning how to use the fetch api for my front-end. I continue to get the XHR 404 POST error.
//Backend file
const express = require("express");
const app = express();
require("dotenv");
const Port = process.env.PORT || 5000;
app.use(express.static("public"));
app.use(express.json());
app.use(
express.urlencoded({
extended: false,
})
);
const nodemailer = require("nodemailer");
const Mail = require("nodemailer/lib/mailer");
require("nodemailer-mailgun-transport");
app.use(express.json());
app.get("/", (req, res) => {
res.sendFile("/public");
res.sendFile("/public/js/mail.js");
});
app.listen(Port, (req, res) => {
console.log(`listening on port ${Port}`);
});
app.post("/email"),
(req, res) => {
FromMailjs = req.body;
console.log(FromMailjs);
const transporter = nodemailer.createTransport({
auth: {
user: process.env.Email,
pass: process.env.Pass,
},
});
const MailOptions = {
from: req.body.Email,
to: process.env.MyEmail,
text: `${req.body.FirstName}, ${req.body.LastName}
, ${req.body.PhoneNumber}, ${req.body.Email}`,
};
transporter.sendMail(MailOptions, (error, info) => {
if (error) {
console.log(error);
res.send("error");
} else {
console.log("Email sent");
res.send("success");
}
});
};
//Frontend file
const ContactForm = document.querySelector(".contact-form");
ContactForm.addEventListener("submit", (e) => {
e.preventDefault();
let FirstName = document.getElementById("Fname");
let LastName = document.getElementById("Lname");
let PhoneNumber = document.getElementById("PhoneNumber");
let Email = document.getElementById("Email");
const FormData = {
FirstName: FirstName.value,
LastName: LastName.value,
PhoneNumber: PhoneNumber.value,
Email: Email.value,
};
const PostOptions = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(FormData),
};
console.log(FormData);
fetch("/email", PostOptions);
});
XHRPOSThttp://localhost:5000/email
[HTTP/1.1 404 Not Found 27ms]
I have tried changing the routes hoping that it was just a routing issue and I still get the same error. I was using XHR before fetch and I got the same 404 error. My front-end is receiving the correct information but I can't get my backend to receive the information.
You have a typo. Please use:
app.post("/email", (req, res) => {
Instead of:
app.post("/email"),
(req, res) => {

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.

Microsoft bot framework webchat hidden secret for direct line -- NODE JS

I need to hide the secret for direct line channel using an HTML webchat, tried this solution but keeps getting me errors while fetching. I got the secret for direct line channel in Azure portal in process.env
Index.js
const dotenv = require('dotenv');
const path = require('path');
const restify = require('restify');
const bodyParser = require('body-parser');
const request = require('request');
const corsMiddleware = require('restify-cors-middleware');
const { BotFrameworkAdapter, MemoryStorage, ConversationState, UserState } = require('botbuilder');
const { EBOT } = require('./eBot');
const ENV_FILE = path.join(__dirname, '.env');
dotenv.config({ path: ENV_FILE || process.env.directLineSecret });
const cors = corsMiddleware({
origins: ['*']
});
const server = restify.createServer();
server.pre(cors.preflight);
server.use(cors.actual);
server.use(bodyParser.json({
extended: false
}));
server.listen(process.env.port || process.env.PORT || 3978, () => {
console.log(`\n${ server.name } listening to ${ server.url }`);
console.log('\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator');
console.log('\nTo talk to your bot, open the emulator select "Open Bot"');
});
// Generates a Direct Line token
server.post('/directline/token', (req, res) => {
const options = {
method: 'POST',
uri: 'https://directline.botframework.com/v3/directline/tokens/generate',
headers: {
'Authorization': `Bearer ${process.env.directLineSecret}`
}};
request.post(options, (error, response, body) => {
if (!error && response.statusCode < 300) {
res.send({
token: body.token
});
} else {
res.status(500).send('Call to retrieve token from DirectLine failed');
}
});
});
server.post('/api/messages', (req, res) => {
adapter.processActivity(req, res, async (context) => {
await ebot.run(context);
});
});
And webchat.html:
<script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
<script>
(async function () {
const res = await fetch('https://directline.botframework.com/v3/directline/tokens/generate', { method: 'POST' });
const webChatToken = await res.json();
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token: webChatToken })
}, document.getElementById('webchat'));
document.querySelector('#webchat > *').focus();
})().catch(err => console.error(err));
</script>
/// UPDATE
The errors:
** Failed to load resource: the server responded with a status of 403 ()
** webchat.js:2 POST https://directline.botframework.com/v3/directline/conversations 403
** webchat.js:2 Uncaught t {message: "ajax error 403", xhr: XMLHttpRequest, request: {…}, status: 403, responseType: "json", …}
What's the way then ?, what am I missing ?
The issue with your particular implementation is, while you have set up an API for generating and serving a token back to Web Chat, you are failing to actually call that endpoint. Instead of
const res = await fetch('https://directline.botframework.com/v3/directline/tokens/generate', { method: 'POST' });
you should have
const res = await fetch('http://localhost:3978/directline/token', { method: 'POST' });
It is this that will make the call to exchange the Direct Line secret for a token and, in turn, will return the token back to your Web Chat instance.
Solved it, the problem was the way the api token function was made, this is the one that worked in order to retrieve the json response from index.js :
server.post('/directline/token', async function(req, res) {
const result = await fetch('https://directline.botframework.com/v3/directline/tokens/generate', {
method: 'POST',
headers: {
Authorization: 'Bearer ' + process.env.DirectLineSecret
}
});
const token = await result.json();
res.send(token);
});
The one I posted in questions was not sending the token response but a huge request ibject instead. Hope it helps !

Express JS is receiving an empty req.body from ReactJS

I am currently having a problem with React and Express JS form submit function. It seems like my nodeJS running on port 5000 is receiving an empty object from my ReactJS running on port 8080 using fetch method.
React : Contact.js
handleSubmit(e)
{
e.preventDefault();
var data = {
name: this.state.name,
contact: this.state.contact,
email: this.state.email,
message: this.state.message,
}
var url = 'http://localhost:5000/api/insertUsers';
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
mode: 'no-cors',
body: JSON.stringify(data),
})
.catch((error) => {
console.log(error);
});
}
NodeJS : server.js
const express = require('express');
const { Client } = require('pg');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.post('/api/insertUsers', function(req, res) {
res.setHeader('Content-Type', 'text/plain')
res.write('you posted:\n')
res.end(JSON.stringify(req.body, null, 2))
});
app.listen(5000, () => {
console.log('listening on port 5000');
});
Change the order of bodyparser middleware like this.
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
You are sending a request with the content-type of 'application/json' but express is expecting a content-type of 'text/json'. Usually, when req.body is empty content-type is the first suspect you should be looking at.
I am ashamed that I struggled with this for hours. I still haven't gotten it to work with file uploads.
But I did get it to work with a normal form by encoding JSON and sending that along with axios, instead of fetch
My js code
var data = {
id: this.state.id,
}
console.log('data',data)
var bodyFormData = new FormData();
bodyFormData.set('id', this.state.id);
var url = ' http://localhost:3000/get-image-by-id';
console.log("bodyFormData: ", bodyFormData);
axios({
method: 'post',
url: url,
data: data,
// headers: {'Content-Type': 'multipart/form-data' }
headers: {'Content-Type': 'application/x-www-form-urlencoded' }
})
.then(function (response) {
//handle success
console.log(response);
})
.catch(function (response) {
//handle error
console.log(response);
});
Form Code
<form method="POST" onSubmit={this.handleSubmit} >
<label>
Transaction ID
<input
type="text"
name="id"
value={this.state.id}
onChange={this.handleInputChange}
/>
</label>
<button type="submit">Submit</button>
</form>
```
EDIT
fetch(url, {
method: 'POST',
body: JSON.stringify(data),
mode: 'no-cors'
}).then((result)=>{
console.log("output" + result.json());
})
.catch((error) => {
console.log(error);
});
EDIT 2
for backend, install cors and add the following lines before route.
var cors = require('cors')
app.use(cors())
EDIT 3
perform npm install morgan then copy these lines inside the code
var morgan = require('morgan');
app.use(morgan('dev'));
I didn't look at your code close enough. My bad
app.post('/api/insertUsers', function(req, res) {
res.setHeader('Content-Type', 'text/plain')
res.write('you posted:\n')
res.end(JSON.stringify(req.body, null, 2))
});
Should be
app.post('/api/insertUsers', function(req, res) {
res.json(req.body)
});
try using axios instead of fetch
I rewrote ur code like this and it works perfectly
server
const express = require('express');
const { Client } = require('pg');
const bodyParser = require('body-parser');
const app = express();
const cors = require("cors");
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/api/insertUsers', function(req, res) {
// console.log(req);
console.log(req.body);
res.send(req.body);
});
app.listen(3001, () => {
console.log('listening on port 3001');
});
react (ensure you have axios installed)
handleSubmit(e){
e.preventDefault();
var data = {
name: "zadiki",
contact: "0702002109",
email: "zadiki",
message: "test",
}
console.log("wow");
var url = ' http://localhost:3001/api/insertUsers';
axios.post(url,data)
.then(response=>console.log(response))
.catch(e=>console.log(e))
}
Hello I ended up getting mine working after I ran into the same problem.
I noticed your react code has "mode: 'no-cors'," that was causing problems with mine so I removed it.
-------- Below is my handle submit code for React ------------
const handleSubmit = (event) => {
event.preventDefault();
const url = "http://localhost:3001/register"
const options = {
method: "POST",
body: JSON.stringify(formData),
headers: {
"Content-Type": "application/json"
}
}
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
}
I used express.json instead of bodyParser. You also had a typo in your express code, it should say res.send instead of res.end
--------- Below is my Node Express Code -----------
const express = require('express');
const app = express();
const cors = require('cors');
const multer = require('multer');
// Middlewares
app.use(cors({ origin: 'http://localhost:3000', }))
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.use(multer().array());
app.post('/register',(req, res) => {
console.log(req.body)
res.status(200)
.json({status:"Success", data:{body: req.body })
});
app.listen(3001, () => console.log(`Running on 3001`))
I was able to send form data using postman and react using the code above. Feel free to change it to accommodate your needs.

Resources