2

I'm a beginner in ReactJS, and I'm trying to improve the writing of my codes, and I ended up getting to the API calls part, I want to improve the reusability of my API calls and set them with a specific folder something like utils / APIcalls.js but I do not know the best way and the correct way to do this, I have the following API call getItems():

Home.jsx

export default class Home extends Component {
    constructor(props) {
        super(props);
        this.state = {
            'items': [],
            isLoading: false,
            error: null,
        };
    }

    componentDidMount() {
        this.getItems()
        this.refresh = setInterval(() => this.getItems(), 100000);
    }

    componentWillUnmount() {
        clearInterval(this.refresh)
    }
    
    getItems() {
        this.setState({ 'isLoading': true });
        fetch('https://xxx/api/article/')
            .then(results => {
                if (results.ok) {
                    return results.json();
                } else {
                    throw new Error('Something went wrong ...');
                }
            })
            .then(results => this.setState({ 'items': results, 'isLoading': false }))
            .catch(error => this.setState({ error, isLoading: false }));
    }

    render() {
        const { isLoading, error } = this.state;

        if (error) {
            return <p>{error.message}</p>;
        }

        if (isLoading) {
            return <Loading />
        }

        return (
            <div className="container" >
                <div className="row align-items-start">
                    <Principal items={this.state.items} />
                </div>
                
                <hr />

                <div className="row align-items-start">
                    <Secondary items={this.state.items} />
                </div>
            </div>
        );
    }
}

I use the same call in multiple places, is there any way to set these calls globally, and call them more easily elsewhere in the code?

To solve this problem problem I used axios to create reusable functions:

I created a folder called by utils, inside that folder I created a file called by apiConfig.js and apiCalls.js:

import API from './apiConfig'

export default {
    getArticles: () => {
        return API.get('article')
            .then(res => res.data)
    },
    getUser: () => {
        return API.get('user')
            .then(res => res.data)
    }    
}

After that, I call that functions in the components using that way:

componentDidMount() {
        this.getItems()
    }

    getItems() {
        this.setState({ 'isLoading': true });
        API.getArticles().then(items => this.setState({ items, 'isLoading': false }))
            .catch(error => this.setState({ error, isLoading: false }));
    }
5
  • 4
    You can extract fetch + first then to a separate function and use it here Commented Nov 5, 2018 at 23:06
  • 1
    How would I extract it? would separate into another folder only with api calls? what would the folder structure look like? Commented Nov 5, 2018 at 23:10
  • It is completely up to you - as far as you are comfortable using it. I would suggest to create one file (/api/index.js) if there is not a huge number of such functions (up to 10-15). If there are more - try to group them somehow (for example domain-drivenly - /api/user.js, /api/products.js, etc) Commented Nov 5, 2018 at 23:14
  • i like API calls to go in actions that return thunks, although I may be biased because that's the structure I learned initially with react/redux Commented Nov 5, 2018 at 23:16
  • 1
    As stated in the comments it is much your own preferences that decide where you want the function to go in your folder structure. Maybe you don't even need a new separate folder if it's just one function. The main goal is to separate out the fetch into a reusable function and then put it in a file where you think it suits your needs and structure of the code best. One more thing you can do is to turn your fetch function into a higher order function. That way you can pass in a function as an argument. That argument function will calculate what to return from the fetch function. Flexible ;) Commented Nov 5, 2018 at 23:24

2 Answers 2

6

I agree with all the comments, your './utils/API.js' would look like this:

export default {
  getItems: () => {
    return fetch('https://xxx.api/article')
      .then(res => res.json());
  },
  otherApiCall: (params) => {
  }
}

The component like so:

import API from '../utils/API';

componentDidMount() {
  const items = API.getItems();
  this.setState({ items });
}

Wherever you import it, this call should result in your items, you can add error handling here or in the component. As HolyMoly commented, in Redux-Thunk I usually handle this in the actions (where the call is sent)

Sign up to request clarification or add additional context in comments.

3 Comments

I did what you quoted, however it is returning me undefined in items, and when I put a return in fetch, then returns me a promises, but not a json, any help for that?
Yes, I did forget return and the res.json() to extract the JSON body in the request. (I corrected the original response) Take a look at this: developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
Thanks, the way of Sean Kim and yours suggested worked perfectly!!
1

In my opinion, I usually used these.

API/Axios_Api.js

import axios from 'axios';

const MYAPI= "YOUR API"
export const AXIOS_API = () => {
axios.get(MYAPI)
.then( res => res.data )
.catch (err => thorw{err})
};

2 Comments

How do I call this function the correct way on the screens? when I'm calling on the screens it's bringing me the promise and not the results.json I need
I need your Json file. because each Json file have a own structure

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.