My controls look like this
return (
<div className='contentDiv'>
<Container>
<Form onSubmit={getFormData}>
<Form.Group className="mb-3" controlId="formBasicName">
<Row><Form.Control name="id" type="number" value={3} readOnly={ true }></Form.Control></Row>
<Row>
<Col>
<Form.Label>Forname:</Form.Label> <Form.Control name="firstname" type="text" placeholder="navn"></Form.Control>
</Col>
<Col>
<Form.Label>Efternavn:</Form.Label> <Form.Control name="lastname" type="text" placeholder="Efternavn"></Form.Control>
</Col>
</Row>
</Form.Group>
<Row><Button type="submit">Create user</Button></Row>
</Form>
</Container>
</div>
)
And the function that is called on submit looks like this
const getFormData = async (event) => {
const data = new FormData(event.currentTarget);
event.preventDefault();
await fetch(`/api/newMember`, {
method: 'POST',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err)
})
};
If I do this in the client (and fill the form with id=3, firsname=Lucky lastname=Luke):
for (let [key, value] of data.entries()) {
console.log(key, value);
}
I get (in the console)
id 3
firstname Lucky
lastname Luke
The server post method that does not receive the data from the client, looks like this
const express = require('express');
const knex = require('knex');
const cors = require('cors');
const bodyParser = require('body-parser');
const app = express();
const port = 3001;
app.post('/api/newMember', (req, resp) => {
const { id, firstname, lastname } = req.body;
console.log(req.body);
const newMember = {
id: id,
firstname: firstname,
lastname: lastname,
};
db('members').insert(newMember)
.then(res => {
resp.send(res)
})
.catch(err => {
console.log(err);
return;
})
})
app.listen(port, () => {
console.log('Server listening on port: ' + port);
});
In the server, I have this code: console.log(req.body);
. It jsut prints {}
Can anyone figure out what I’m doing wrong?
—————— Update ———————-
I found out that the problem does not lie on the server, but rather at this spot
const data = new FormData(event.currentTarget);
event.preventDefault();
await fetch(`/api/newMember`, {
method: 'POST',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
If fx I instead do: body: JSON.stringify({firstname: 'Test'})
then the data is sent to the server
So the body: JSON.stringify(data)
seems to be causing problems somehow
2
Answers
Add the body parser middleware or use express.json middleware before the route
The content type of formData is multipart/form-data.
This is the point to be kept while coding for it.
Please see below a sample code (app and server) which does the following actions.
Please start reading this by seeing the output screens enclosed under the section "Test run".
The important points to note here are the following:
a) Each input element in the form must have name attribute, otherwise the FormData constructor will fail to create an object. You can read on it from here.
b) When the FormData is transferred to server, the content-type
will be automatically set by the browser to multipart/form-data. Therefore
it does not need to be specified in the fetch request. This has been demoed in the sample code by printing the same at the server console. Please see and confirm the respective output shown in the Test run section below.
c) Since the content type is multipart/form-data, the server needs to parse the incoming data using the middleware destined for it. Multer is the middleware demoed in this sample code. Please note that none of the built-in middleware in Express can handle this content type.
d) The call upload.any() is responsible to create a req.body object which will include all the text fields in the incoming data. For more about Multer, please see here
App.js (React)
server.js (Express)
Test run
React App:
Express API received the data, and responded to the client, the client printed it in the console
The content type set by the Browser which printed at the server console