37

I am trying to rewrite my ajax call to fetch:

Ajax:

  $.post({
    context: this,
    url: "/api/v1/users",
    data: { 
      user: 
        {
          email: email,
          password: password
        } 
    }
  }).done((user) => {
  }).fail((error) => {
  })

Fetch:

  fetch('/api/v1/users', {  
  method: 'POST',
  headers: {
    "Content-Type": "application/json"
  },      
    body: { 
    "user" : 
      {
        "email" : email,
        "password" : password
      } 
  }
  })
  .then(res => {  
    if (res.status !== 200) { {
        console.log("error")
      })          
    } else {
      res.json().then(data => {
        console.log(data)
      })
    }
  })

I am getting an error empty params ~ bad request from my server.

I also found this way to do it, but in this code below I am getting an error: Unexpected token.

  var payload = { 
    "user" : 
      {
        "email" : email,
        "password" : password
      } 
  };

  var data = new FormData();
  data.append( "json", JSON.stringify( payload ) );

  fetch('/api/v1/users', {  
  method: 'POST',
  headers: {
    "Content-Type": "application/json"
  },      
    body: data
  })

How can I rewrite the ajax request to fetch?

Petr
  • 1,853
  • 2
  • 25
  • 49

8 Answers8

64

Followed this topic on github: https://github.com/matthew-andrews/isomorphic-fetch/issues/34

The solution to my question is using the JSON.stringify function and set Content-Type header to application/json. Not pretty sure why the second attempt in my question didn't work though.

fetch('/api/v1/users', {  
    method: 'post',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({ "user": {
      "email" : email,
      "password" : password
    }}),
})

Official MDN Documentation:

var myHeaders = new Headers();
myHeaders.append('Content-Type', 'application/json');

fetch('/contact-form', {
    method: 'POST',
    headers: myHeaders,
    mode: 'cors',
    cache: 'default',
    body: JSON.stringify(fields)
}).then(() => {
    dispatch(contactFormSubmitSuccess());
});
Petr
  • 1,853
  • 2
  • 25
  • 49
20

TL;DR Without mode: 'cors' your JSON body won't go through.

I wrestled with this for a bit. cors was the issue. Assuming you are performing a request from one domain to another (i.e. from localhost:8080 to localhost:3000) you need to have mode: 'cors' in the fetch settings & your receiving domain (localhost:3000) needs to allow requests from the sending domain (localhost:8080).

So the above description in code:

request from localhost:8080 to localhost:3000

fetch('http://localhost:3000/users/sign_in', {
      method: 'POST',
      mode: 'cors', // this cannot be 'no-cors'
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        "user": {
          "email": `${this.state.userEmail}`,
          "password": `${this.state.userPass}`
        }
      }),
    })

And then make sure your receiving domain localhost:3000 allows CORS from localhost:8080.

BigRon
  • 3,182
  • 3
  • 22
  • 47
12
headers: {'Content-Type': 'application/json'}

already answered

Edmunds22
  • 715
  • 9
  • 10
  • 2
    yeah, can not stress the header enough. I spent way too long confused, when the issue was me misspelling application in the header. First step is to check for typos. – Jacob Cafiero Jun 13 '19 at 21:44
  • That literally happened to me too with the exact same fetch functionality. Can stress what Jacob C. said enough. Typos people! – incalite Nov 10 '19 at 00:04
  • for me it was 'header: {'Content-Type': 'application/json'}'. bloody typos – NickW Mar 24 '21 at 16:57
  • without an s, it just cost you another day. :( – Yewness Apr 11 '21 at 06:33
9

worked in this way when sending body as json failed.

        var formData = new FormData();
        formData.append('key1', 'value1');
        formData.append('key1', 'value2');

        fetch('url', {
            method: 'post',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'multipart/form-data'
            },
            body: formData
        }`)`

EDIT: In my case, the server only identified the content through the form-data submission. The code was not written to read the request body as json. So there is a possibility to have an issue with your server side code as well.

buddhiv
  • 692
  • 1
  • 7
  • 24
8

If you're using an Express server to handle the requests, make sure you add in this line:

app.use(express.json({limit:'1mb'}))
Matan Livne
  • 173
  • 3
  • 6
5

The only thing working for me was to put

app.use(express.json())

in my main server file.

David Chavez
  • 138
  • 1
  • 8
2

You should try this:

fetch('/api/v1/users', {
    method: 'post',
    body: JSON.stringify({"user":{
        "email": email,
        "password": password
    }}),
});

fetch API

gamboa
  • 141
  • 3
  • 1
    Thanks, it's basically the same like my second example in my question. It's still showing me params missing although the ajax version works just fine. – Petr Oct 04 '16 at 10:31
1

Try putting (body-parser) at the top of your app.js / server.js :

app.use(bodyParser.json());
Martin CR
  • 1,250
  • 13
  • 25
Hamied Amr
  • 11
  • 3