skip to Main Content

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


  1. Add the body parser middleware or use express.json middleware before the route

    const express = require("express");
    const knex = require("knex");
    const cors = require("cors");
    const bodyParser = require("body-parser");
    
    const app = express();
    const port = 3001;
    
    app.use(bodyParser.json())
    
    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);
    });
    
    Login or Signup to reply.
  2. 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".

    // a) The React app provides a form.
    
    // b) The app takes two sample inputs.
    
    // c) It uses formData object to pass values to the server. 
    
    // d) The server receives the same.
    
    // e) It sends back the values in its response
    
    // f) The client app receives the same and prints it in the console.
    

    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)

    export default function App() {
    
      function handleSubmit(e) {
        e.preventDefault();
        const formData = new FormData(e.target);
    
        fetch('http://localhost:4000/newdata', {
          method: 'POST',
          body: formData,
        })
          .then((response) => {
            if (!response.ok) {
              throw new Error(`Response status ${response.status}`);
            } else {
              return response.text();
            }
          })
          .then((data) => console.log(data))
          .catch((error) => console.log(error));
      }
    
      return (
        <form onSubmit={handleSubmit} name="formdata" id="formdata">
          <label>Input 1</label>
          <input type="text" name="input1" id="input1"></input>
          <br />
          <label>Input 2</label>
          <input type="text" name="input2" id="imput2"></input>
          <br />
          <button type="submit">Submit data</button>
        </form>
      );
    }
    

    server.js (Express)

    const express = require('express');
    const cors = require('cors');
    const upload = require('multer')();
    
    const app = express();
    app.use(cors());
    
    app.post('/newdata', upload.any(), (req, res) => {
      console.log(req.get('content-type'));
      const { input1, input2 } = req.body;
      res.send(`data received : ${input1} , ${input2}`);
    });
    
    app.listen(4000, () => console.log('l@4000'));
    

    Test run

    React App:

    React app

    Express API received the data, and responded to the client, the client printed it in the console

    Express API receives the data

    The content type set by the Browser which printed at the server console

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search