6

I am trying to use module.exports to create a 'global' function which I can use in my React project to make API calls using Axios.

I have tried the following...

import axios from 'axios';

module.exports = {
    fetchApi: function (endPoint) {
        var encodedURI = window.encodeURI('http://localhost:3001/' + endPoint);

        return axios.get(encodeURI)
            .then(function (response) {
                return response.data
            })
    }
}

//call function in other components like this
componentDidMount () {
    fetchApi.fetchApi(this.setState.endPoint)
    .then(function (endPoint) {
        console.log("API endpoint: " + endPoint)
    })
}

this returns the error... 'fetchApi' is not defined no-undef

I am aware that usually you can import and export components using export default but I thought this wasnt required if using module.export.

Also, if I try to import like this...

import fetchApi from '../../../utils/api'

I get the following error... Attempted import error: '../../../utils/api' does not contain a default export (imported as 'fetchApi').

Any help appreciated. Thanks.

Edit:

import axios from 'axios';

Solution (Edit)...

api.js

const api = {
    fetchApi: function(endPoint){
        var encodedURI = window.encodeURI('http://localhost:3001/' + endPoint);
        console.log(encodedURI)

        return axios.get(encodedURI)
            .then(function (response) {
                return response.data

            })
    }
}

export default api;

Sites.js

import api from '../../../utils/api'

    //single api call
    componentWillMount = async () => {
        api.fetchApi('sites')
            .then(data => {
                console.log(data);
                this.setState({ rows: data.rows, columns: data.columns })
            })
            .then(async () => {
                this.setState({ tableRows: this.assemblePosts(), isLoading: false })
            });
    }

This gives me access to the following api endpoint...

http://localhost:3001/sites

Thanks for your help.

Steven Collins
  • 373
  • 2
  • 8
  • 20
  • 2
    Note that `module.exports` is a Node.js thing (or more accurately, a CommonJS thing) used to express what is exported from a module. I'm not sure you should be using it in a React/ES6 environment. See [es6 equivalent for module.exports](https://stackoverflow.com/q/37772749/215552) – Heretic Monkey Jul 31 '19 at 13:50
  • 1
    @HereticMonkey I use it all the time with react, it's all about babel :) – silencedogood Jul 31 '19 at 13:51
  • 1
    @HereticMonkey This is common practice in the field right now my friend. Browserfy, Babel, etc are all widely accepted tools for this purpose. – silencedogood Jul 31 '19 at 13:54
  • 1
    Possible duplicate of [es6 equivalent for module.exports](https://stackoverflow.com/questions/37772749/es6-equivalent-for-module-exports) – Emile Bergeron Jul 31 '19 at 15:05
  • @HereticMonkey It's really normal to use both, just not mixed in the same file. Your build scripts or server-side scripts will be using CommonJS module while React is commonly seen to use ES6 module syntax in the same project. Since some files may be shared (some config), most babel configuration (needed for ES6+ anyway) will work with both syntaxes. – Emile Bergeron Jul 31 '19 at 15:13

2 Answers2

12

I would advice to not mix require and es6 import syntax. Stick with es6 syntax. Same thing with es6 syntax.

import axios from 'axios';

const helpers = {
    fetchApi: function(){

    }
}

export default helpers;

Usage

import helpers from './helpers';

helpers.fetchApi()
tarzen chugh
  • 10,561
  • 4
  • 20
  • 30
  • This answer is better, because you shouldn't mix two different styles of import/ export. It just makes your code less understandable. Standards across a code base are important. – Cal Irvine Jul 31 '19 at 14:09
4

module.exports should export a function, not an object.

module.exports = function() {}

However, you may be better off utilizing named exports if you have multiple functions in your api:

exports.fetchApi = function() {}

Also, you may want to utilize an async function here with await, which will help clean up all of the .then()

silencedogood
  • 3,209
  • 1
  • 11
  • 36
  • 1
    Axios get always returns a promise, so it should be async already. – Cal Irvine Jul 31 '19 at 14:08
  • 2
    @silencedogood any code that returns a promise is async code. You can await it, or you can .then() it wherever you are using it. – Cal Irvine Jul 31 '19 at 14:13
  • And in order to `await` it, it needs to be an `async` function... Or, as you mentioned, you could just utilize the `.then` syntax. Just a matter of preference. – silencedogood Feb 04 '20 at 17:19