0

I'm a bit confused on where I should call an API while using React, I've been putting the call on componentDidMount and doing setState there, like so:

  constructor(props) {
    super(props);

    this.state = {info: []};
  }

  componentDidMount() {
    this.ObtenerVariables(this.props.enlace1, this.props.enlace2);
  }
  ObtenerVariables(consulta1, consulta2){
    var httpRequest = new XMLHttpRequest();
    httpRequest.open('GET', consulta1,false);
    httpRequest.send();
    var cons1 =JSON.parse(httpRequest.response);
    var cantArticulos = cons1.data[0].cantidad_articulos;

    httpRequest.open('GET', consulta2,false);
    httpRequest.send();
    var cons2 =JSON.parse(httpRequest.response);
    var cantAutores = cons2.data[0].cant_autores;

    this.setState({ info: [cantArticulos, cantAutores] })
  }

and then just access the information like so this.state.info[0]

however I've seen some people online say that this is not good because it will give you performance issues, which is exactly the opposite of what I want, I need the website to load faster.
Is this a bad practice and is it affecting performance of the website? What would be a better way to do this? Take into account that this website needs to make around 16 API requests.

Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
Tammy Moscoso
  • 57
  • 1
  • 6
  • 2
    componentDidMount in classes and useEffect(() => {}, []) in functional components. – Ajeet Shah May 25 '20 at 21:41
  • 1
    Does this answer your question? [what is right way to do API call in react js?](https://stackoverflow.com/questions/38742334/what-is-right-way-to-do-api-call-in-react-js) – Emile Bergeron May 25 '20 at 21:46
  • @EmileBergeron sort of, i had already seen that question but my question is more of a "is doing it this way affecting performance and is there a more efficient way to do it" – Tammy Moscoso May 25 '20 at 21:51
  • While not impossible to make it work with `XMLHttpRequest`, you should really consider the new `fetch` API or the `axios` request lib. – Emile Bergeron May 25 '20 at 21:57
  • 1
    The performance hit comes from the fact that these requests are not parallel, so it's waiting for the first one to finish before sending the next one, which looks unnecessary here. – Emile Bergeron May 25 '20 at 21:59
  • Maybe this one is a better question to help with your use-case: [Multiple fetch requests with setState in React](https://stackoverflow.com/q/49754270/1218980) – Emile Bergeron May 25 '20 at 22:03

1 Answers1

0

Best place for Api call is componentDidMount for class component and useEffect(() => { /* ... */}, []) for functional component.

Please check both example below:

Class Component

import React from "react";
import axios from 'axios';

export default class PostListPage extends React.Component {
    state = {
        posts: []
    };

    componentDidMount() {
        axios.get(`https://jsonplaceholder.typicode.com/posts`)
            .then(res => {
                const posts = res.data;
                console.log(posts);
                this.setState({posts:posts});
            })
    }

    render() {
        return (
            <React.Fragment>
                <ul>
                    {
                        this.state.posts? this.state.posts.map(post => <li key={post.id}>{post.title}</li>) : null
                    }
                </ul>
            </React.Fragment>
        );
    }
}

Functional Component

import React, {useEffect, useState} from "react";
import axios from 'axios';

export default function PostListPage() {
    const [posts, setPost] = useState([]);
    let signal = axios.CancelToken.source();

    useEffect(() => {
        let isSubscribed = true;
        axios.get('https://jsonplaceholder.typicode.com/posts', {
            cancelToken: signal.token,
        })
            .then(res => {
                const posts = res.data;
                setPost(posts);
            }).catch(err => {
            console.log(err);
        });
        return function cleanup() {
            isSubscribed = false;
            signal.cancel('Api is being canceled');
        }
    }, []);

    return (
        <React.Fragment>
            <ul>
                {
                    posts? posts.map(post => <li key={post.id}>{post.title}</li>) : null
                }
            </ul>
        </React.Fragment>
    );
}
Khabir
  • 5,370
  • 1
  • 21
  • 33