1

I am using the fetch api polyfill by GitHub with React. The example for submitting a form is as follows:

var form = document.querySelector('form')

fetch('/users', {
    method: 'post',
    body: new FormData(form)
})

My code currently looks something like this inside the component

handleSubmit (event) {
    event.preventDefault();

    fetch('/api/user/', {
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        method: 'post',
        body: JSON.stringify(this.state)
    }).then(function(response) {
        console.log(response);
    })
},

In the app state I am holding the data being sent. It's a simple object.

{
    email: 'someemail@email.com',
    password: 'password',
    name: 'Some Name'
}

I have tried passing the form itself from the event event.target as well as getting the form through an the ID attribute and passing it to the body.

On the server I am using NodeJs to catch the form body in the request. But the request is empty if I don't pass the header 'Content-Type': 'application/x-www-form-urlencoded'. But when I do pass it the entire body is the value with an empty key, but only when I use JSON.stringify(this.state). As follows:

'{email: 'someemail@email.com',password: 'password',name: 'Some Name'}': ''

I have also tried passing no headers, and the following header.

headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
}

I am adding the fetch module through webpack as a plugin.

new webpack.ProvidePlugin({
    'Promise': 'exports?global.Promise!es6-promise',
    'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch'
})

I'm stuck, any help is appreciated.

Currently I have a really ugly hack on the server to convert the key=>value pair into an object again, but It's shameful event to share it.

var userInfo = req.body;
var tempVals;
//hack to fixed fetch
if(!userInfo.email) {
    for(values in req.body) {
        tempVals = JSON.parse(values);

        if(tempVals.email) {
            userInfo = tempVals;
            break;
        }
    }
}

...I said it was ugly.

UPDATE

Thanks to Michelle, I was able to figure figure out that it was something to do with parsing the form data. I used the body-parser module. I could not get the data to be read with my current set up. I had to change my code on the client side to as follows:

handleSubmit (e) {
    e.preventDefault();

    fetch('/api/user/', {
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        },
        method: 'post',
        body:  JSON.stringify(this.state)
    }).then(function(response) {
        console.log(response);
    })
} 

and in the backend I had to add the JSON body parser to my route as follows

var bodyParser = require('body-parser');
var jsonParser = bodyParser.json();

app.post('/user', jsonParser, function(req, res) {
    //do something with the data
});
Jose Carrillo
  • 1,830
  • 3
  • 16
  • 19

1 Answers1

1

The example you posted:

var form = document.querySelector('form')

fetch('/users', {
    method: 'post',
    body: new FormData(form)
})

is the example for posting form data (see this Stack Overflow question for more information). You're trying to submit JSON data, and the very next example in the README is the method you should use:

fetch('/users', {
  method: 'post',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'Hubot',
    login: 'hubot',
  })
})

so your code would look like

handleSubmit (event) {
    event.preventDefault();

    fetch('/api/user/', {
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        },
        method: 'post',
        body: JSON.stringify(this.state)
    }).then(function(response) {
        console.log(response);
    })
},

You will also need to have appropriate middleware installed in your Express app to parse JSON bodies (for example, body-parser):

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

// ...

app.use(bodyParser.json());

app.post('/user', function(req, res) {
    //do something with the data
});
Community
  • 1
  • 1
Michelle Tilley
  • 157,729
  • 40
  • 374
  • 311
  • Hi Michelle, Thanks for answer. I have actually tried, both. I tried submitting the form from `event.target`, but the backend gets an empty object as `{}`. I tried doing it as the example as well. In a desperate move I tried all of them from the documentation including sending the data as JSON – Jose Carrillo Jan 06 '16 at 06:49
  • @JoseCarrillo Do you have a body parsing module installed in your Express middleware? You will still need it even to parse form encoded bodies. – Michelle Tilley Jan 06 '16 at 06:51
  • Hi Michelle, yes I am using the `body-parser` module. `var bodyParser = require('body-parser')`. This is the setup in my Node app `var urlencodedParser = bodyParser.urlencoded({ extended: false })` – Jose Carrillo Jan 06 '16 at 07:00
  • @JoseCarrillo In that case, I'd expect using `'Content-Type': 'application/x-www-form-urlencoded'` and `body: new FormData(evt.target)` (assuming `evt.target` is the form) to work. =\ – Michelle Tilley Jan 06 '16 at 07:01
  • Thanks for the help, It does have something to do with a body parser middle ware. I am not sure why. I included the `body-parse`'s json parser and sent the data as JSON with the `application/json` headers that did the job. Thanks for pointing me in the right direction. I updated my code. If you want to update your answer I can mark it as the answer. – Jose Carrillo Jan 06 '16 at 07:08