19

I'm using axios.create() to pass in a baseURL and some default query params like this

axios.create({
    baseURL: 'http://somebigurlhere',
    params: {
        part: 'part',
        maxResults: 5,
        key: 'key'
   }
});

When I use

axios.get('/search', {
    params: {
        q: 'word'
    }
});

the default params do not get merged in the GET call.

What I get is http://somebigurlhere/search?q=word

instead of http://somebigurlhere/search?part=part&maxResults=5&key=key&q=asd

I tried putting the configuration in many other ways but it still doesn't work. Am i doing something wrong here ?

I tried the same in other projects and it is working there. Just created a new react app with create-react-app and this doesn't seem to work anymore.

pallav_125
  • 211
  • 1
  • 2
  • 8
  • Might also find this useful: https://stackoverflow.com/questions/48261227/use-axios-get-with-params-and-config-together – Woodrow May 31 '19 at 14:57
  • You are correct, based on the source code - default parameters are not merged, if you supply parameters they replace the defaults - you need to use an interceptor to merge them in – sylvanaar May 31 '19 at 19:05
  • https://github.com/axios/axios/issues/2190 – sylvanaar May 31 '19 at 19:48
  • @sylvanaar this should be the answer and get more focus.. – Mosh Feu Dec 19 '19 at 07:17
  • This is a bug, [my PR](https://github.com/axios/axios/pull/2656) has been merged and should get released in 0.20.0. – jonrsharpe Feb 16 '20 at 09:50

4 Answers4

26

I solved it using 2 ways:

  1. Using default params and spreading them when using the request

    export const API_DEFAULT_PARAMS = {
      part: 'part',
      maxResults: 5,
      key: 'key'
    }
    
    export default axios.create({
      baseURL: 'http://somebigurlhere',
    });
    

    Then to use it:

    import api, { API_DEFAULT_PARAMS } from './place/where/previous/file/is';
        ....
    api.get('/search', {
       params: {
        // spread the default params
         ...API_DEFAULT_PARAMS,
        // add your own parameters here
         q: 'word',
       }
    });
    
  2. Using interceptors as a user suggested here

    const instance = axios.create({
      baseURL: 'http://somebigurlhere',
    }); 
    
    instance.interceptors.request.use(config => {
      config.params = {
       // add your default ones
       part: 'part',
       maxResults: 5,
       key: 'key',
       // spread the request's params
        ...config.params,
      };
      return config;
    });
    
    export default instance; 
    

    Then to use it

    import api from './place/where/previous/file/is';
    ...
    api.get('/search', {
     params: {
       q: 'word',
     }
    });
    

I like the interceptor approach more because it abstracts the default params to the instance file itself and you don't have to import and spread an object every time you use the instance.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
AliF50
  • 16,947
  • 1
  • 21
  • 37
  • 3
    This should be accepted as the correct answer. Very well explained and useful! – Casper Wilkes Dec 19 '19 at 09:21
  • 3
    There is a small bug in option #2 for interceptors. The ...config.params has to be at the end so that it overrides the defaults, not other way around. So a correct definition would look like this: config.params = { ...defaults, ...config.params } – julie-ng Dec 23 '19 at 10:25
2

Downgrade the Version of axios. it has some issues with latest version

npm install --save axios@0.18.1
yasarui
  • 6,209
  • 8
  • 41
  • 75
  • 2
    Currently this is the only easiest option if you are still in learning stage! track the issue here https://github.com/axios/axios/issues/2190 – tHeSiD Jul 23 '20 at 23:42
-2

Use should return a custom object like this

const custom = axios.create({
    baseURL: 'http://somebigurlhere',
    params: {
        part: 'part',
        maxResults: 5,
        key: 'key'
   }
});

Then use the custom object to make request

custom.get('/search', {
    params: {
        q: 'word'
    }
});

Please try similar example in this codepen

Then you will see in the console, the query parameters are merged together in the request (blue line) as following image enter image description here

Chiến Nghê
  • 736
  • 2
  • 9
  • 25
-3

Just create a config object and pass it to your Axios.get request.

const config = {
    baseURL: 'www.someurl.com',
    params: {
        part: 'part',
        maxResults: 5,
        key: 'key'
    }

  }

axios.get('/waffles', config);

Example:

const config = {
    baseURL: 'https://reqres.in',
    params: {
        per_page: 3
    }
}

axios.get('/api/users?page=1', config).then(response => {console.log(response)}).catch(err => {console.log(err)});
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

If you would like to use axios.create you need to assign it to a variable as an axios instance object and then run your request against that instance.

var instance = axios.create({
    baseURL: 'https://reqres.in',
    params: {
        per_page: 5
    }
});
instance.get('/api/users?page=1').then(response => {console.log(response)}).catch(err => {console.log(err)});
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>


So for your exact example, as I said, assign axios.create to a variable then issue your .get from that.

var instance = axios.create({
        baseURL: 'http://somebigurlhere',
        params: {
            part: 'part',
            maxResults: 5,
            key: 'key'
        }
    });


instance.get('/search', {
    params: {
        q: 'word'
    }
});



Bigger Edit This edit shows how to do this in react per OPs comment in my answer. The actual sandbox demonstrating htis can be found here: https://codesandbox.io/embed/cranky-aryabhata-2773d?fontsize=14

//axios_control.js file

import axios from "axios";
export const instance = axios.create({
  baseURL: "https://reqres.in",
  params: {
    per_page: 5
  }
});


// index.js file Take note of the import from axios_control and the usage to log the return data right before the render.

import React from "react";
import ReactDOM from "react-dom";
import { instance } from "./axios_control";

import "./styles.css";

function App() {
  instance.get("/api/users").then(response => {
    console.log(response);
  });

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
basic
  • 3,348
  • 3
  • 21
  • 36
  • This is for a custom configuration across a react app. I don't think it will be a good idea creating a config object everywhere i make the request. the second part is right and I'm exporting the instance which doesn't seem to work for me – pallav_125 May 31 '19 at 15:02
  • If the config is going to be the same in the react app I don't see why you can't export it from a single location. Second, the second way I have shown is the axios way to use axios.create, if you are having issues with that you have other issues in yoru code. – basic May 31 '19 at 15:04
  • I am able to export it from a single location but as i mentioned in my question, it isn't working. It was working earlier but with the new app that i create from create-react-app, this isn't working for me anymore. export obviously works, the params getting appended to the url doesn't – pallav_125 May 31 '19 at 15:07
  • @pdjinn Here is my exact code in a react sandbox. https://codesandbox.io/embed/cranky-aryabhata-2773d?fontsize=14 axios_control.js is exporting my object. – basic May 31 '19 at 15:12
  • Thanks @basic. Just found out that axios v0.19.0 got published recently and this code is not working there. For v0.18.0 even my code is working perfectly. – pallav_125 May 31 '19 at 15:41