Home > other >  Not able to pass JSON data using FETCH
Not able to pass JSON data using FETCH

Time:02-23

I am having an API Service build on node js running on port 3001 and a web UI using REACT & running on port 3000. I have to POST details from Web page to the API in JSON Format. I am able to hit the API, however I could not get the JSON on the API. Its being received as {}. However the API is working fine from postman.

Could some one please share light on where i am missing.

Source code of API 

const util = require('util')
const request = require("request");
const express = require('express')

const app = express();
const port = 3001

app.use(express.json());
app.use(express.urlencoded( {extended: false}));
const bodyParser = require('body-parser');
const { json } = require('express/lib/response');

app.post('/PostPatronDetailsone',(req,res) => {
    
    async function run() {
        try {       
            console.log('Request received from REACT ONE');
            // parse application/json
            app.use(bodyParser.json())
            console.log(req.body);
            
            // Respond back
            res.send('Transaction Sent');
        } finally {
            // Ensures that the client will close when you finish/error
        }
    }
    run().catch(console.dir);    
});

app.listen(port, () => console.log('Server is listening at port '   port));

Code Snippet of Web making the HTTP POST

import React from 'react';

class Signup extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
          postId: null
        };

    }

    async componentDidMount() {
      // Simple POST request with a JSON body using fetch
      let payload = {'first_name': 'TEST' };
      var data = new FormData();
      data.append( "json", JSON.stringify( payload ) );

      const requestOptions = {
          method: 'POST',
          mode: 'no-cors',
          headers: { 'Content-Type': 'application/json','Accept':'application/json' },
          body: data,
          redirect: 'follow'
      };
    
      var response = await fetch('http://localhost:3001/PostPatronDetailsone', requestOptions);
      var data1 = await response.json();
      var data2 = data1.text();
      alert(data2);
      //this.setState({ postId: data1.insertedid });             

    }

    render() {
        const { postId } = this.state;
        return (
          <div className="card text-center m-3">
          <h5 className="card-header">Simple POST Request</h5>
          </div>
        );
    }
}

export default Signup; 

Console Output of API Service 
Server is listening at port 3001
Request received from REACT ONE
{}
Request received from REACT ONE
{}

CodePudding user response:

It is because you send formData, instead stringify the object and send it to body like this:

    async componentDidMount() {
  // Simple POST request with a JSON body using fetch
  let payload = {first_name: 'TEST' };

  const requestOptions = {
      method: 'POST',
      mode: 'no-cors',
      headers: { 'Content-Type': 'application/json','Accept':'application/json' },
      body: JSON.stringify(payload ),
      redirect: 'follow'
  };

  var response = await fetch('http://localhost:3001/PostPatronDetailsone', requestOptions);
  var data1 = await response.json();
  var data2 = data1.text();
  alert(data2);
  //this.setState({ postId: data1.insertedid });             

}

CodePudding user response:

Please change the code as follows:

let payload = {'first_name': 'TEST' };
fetch('http://localhost:3001/PostPatronDetailsone',{
  body:JSON.stringify(payload),
  method:'post',
  mode: 'no-cors',
  headers: {
    "Content-Type": "application/json"
  },
  
}).then((res)=>res.json()).then((data)=>console.log(data));

And from controller in backend remove that line as you are already using express.json() which is equivalent to that line:

app.use(bodyParser.json()) // remove it

CodePudding user response:

You have 3 key problems here:

  1. You are posting a FormData object (which gets converted to a multipart/form-data encoding) and not JSON
  2. You are setting no-cors mode which causes the browser to silently discard any instructions to do anything that would require CORS permission (such as setting the application/json content-type or reading the response)
  3. There won't be a text() method on anything parsed from JSON

const data = {'first_name': 'TEST' };
const payload = JSON.stringify(data)

const requestOptions = {
    method: 'POST',
    headers: { 'Content-Type': 'application/json','Accept':'application/json' },
    body: payload,
    redirect: 'follow'
};

const response = await fetch('http://localhost:3001/PostPatronDetailsone', requestOptions);
const parsed_json = await response.json();
console.log(parsed_json);

You will also need to change the server-side code to grant permission to the JavaScript to read the response and send the JSON formatted request. Use the cors module for that.

app.use(cors());

Also note that body parsing middleware needs to be set up when the application starts and not in the middle of a route. The body-parser module has been obsoleted as Express has its features built-in now.

The following is good:

app.use(express.json());

The following is bad:

const bodyParser = require('body-parser');

and

app.use(bodyParser.json())

Your route code doesn't need to be any more complex than:

app.post('/PostPatronDetailsone', async (req,res) => {
    console.log('Request received from REACT ONE');    
    console.log(req.body);
    res.json('Transaction Sent');
});

Note that since you are trying to parse the response as JSON in the client side code, I've had to change send to json so that the server outputs JSON instead of plain text.

  • Related