2

Take the following Axios example:

axios.post(this.reportURL, reportData, {
  params: {
    param1: paramValue1,
    param2: paramValue2
  },
});

How can I do the same thing using fetch API? I see that parameters are done like this:

fetch(this.reportURL, {
  method: "POST",
  body: "param1=paramValue1&param2=paramValue2",
  headers: 
    {
      "Content-Type": "application/x-www-form-urlencoded"
    }

})

Since the body key is being used to store the parameters, do I need to serialize my entire reportData object and concatenate it to the existing parameters?

I don't understand why Fetch API is using the body key for parameters.

Additionally, this is not my own API and I cannot change the expected POST request.

user3379893
  • 183
  • 1
  • 2
  • 10
  • Unless I am misreading the axios docs, those are not same. The first, will append those params as a URL params i.e. `example.com?p1=foo&p2=bar`. The second will append the body as the actual body of the request, not as part of the URL. Which one are you *trying* to do. – zero298 Aug 20 '18 at 16:46
  • You cannot `extract` the pieces you need from reportData and create your own object to pass to `fetch`? What do you mean you cannot change the POST request? – Akrion Aug 20 '18 at 16:48
  • @zero298 I am trying to do both, as the API requires parameters as well as JSON data. – user3379893 Aug 20 '18 at 16:54
  • @Akrion I can create my own object, I guess I am wondering if what you suggested is indeed the correct approach to this. – user3379893 Aug 20 '18 at 16:55

5 Answers5

6

Frustratingly, fetch() does not really provide a "clean" way to provide query string URL parameters. You have to just put them in the URL that you are fetching directly. It's a point of contention that you can read about on the GitHub: How to pass url query params? #256.

There are a few ways that you can simulate it:

const url = new URL("http://www.example.com");

const params = {
  foo: "bar",
  fizz: "buzz"
};

const data = {
  more: "data",
  that: "I",
  want: "to",
  send: "please"
};

Object.entries(params).forEach(([k, v]) => url.searchParams.append(k, v));
console.log(url);

fetch(url, { // URL as http://www.example.com/?foo=bar&fizz=buzz
  method: "POST",
  body: JSON.stringify(data) // The actual body
});

Since you have application/x-www-form-urlencoded in your question as well, you may want to take a look at this question also: Post a x-www-form-urlencoded request from React Native.

zero298
  • 25,467
  • 10
  • 75
  • 100
  • Thanks for the github discussion, that was quite helpful. The x-www-form-urlencoded content-type header was unintentional; I pasted from another example sorry about the confusion. As I move our application from Axios to fetch it seems like there are more than a few hurdles I need to overcome. – user3379893 Aug 20 '18 at 17:30
0

If you need to construct query param string from a hash and you use jQuery on your site, you can do:

var url = "http://www.abx.com?" + $.param({foo: "bar", baz: "kuuq"}) fetch(url)

Here is what the fetch standard recommends in their documentation (also see discussion in whatwg/fetch#56):

var url = new URL("https://geo.example.org/api"), params = {lat:35.696233, long:139.570431} Object.keys(params).forEach(key => url.searchParams.append(key, params[key])) fetch(url).then(...)

This requires that the browser implements url.searchParams. A polyfill might be needed for older browsers.

Read over this quickly, but hopefully that helped

Src: https://github.com/github/fetch/issues/256

Luca Kiebel
  • 9,790
  • 7
  • 29
  • 44
Blake Bell
  • 376
  • 5
  • 16
0

You can do body: JSON.stringify({ param1: paramValue1, param2: paramValue2 })

Ziyo
  • 604
  • 5
  • 10
0

It looks like you're close, but on the second example, as you're making a POST request, the parameters will usually go on the body of the request as JSON:

fetch(this.reportURL, {
  method: "POST",
  body: JSON.stringify({
    param1: paramValue1,
    param2: paramValue2
  })    
})
Vitor M. Barbosa
  • 3,286
  • 1
  • 24
  • 36
0

You can extract the pieces from reportData into another object and pass that one to fetch by JSON.stringify it.

Fetch also supports FormData but that is not that much different that the object approach I already mentioned.

As per the docs you could specify the body as the following:

  1. ArrayBuffer
  2. ArrayBufferView (Uint8Array and friends)
  3. Blob/File
  4. string
  5. URLSearchParams
  6. FormData
Akrion
  • 18,117
  • 1
  • 34
  • 54