Search code examples
javascriptreactjstypescriptuse-effectuse-state

Infinite Re-rendering of React Functional Component using Axios and useState/useEffect?


I am trying to create a React Functional Component using Typescript that will get data from an API and then send that data to another component, however, I am getting an error of "Error: Too many re-renders. React limits the number of renders to prevent an infinite loop."

Please offer any advice!

useEffect(() => {
    await axios.get('https://quote-garden.herokuapp.com/api/v3/quotes/random').then((resp) => {
            setQuote1(resp.data.data[0]);
        });
    getQuote();
}, []);

Snippet of Code Causing Error

EDIT: Here is the entire File where the error is occurring.

import React, { useEffect, useState } from 'react';
import { Row, Col, CardGroup } from 'reactstrap';
import axios from 'axios';

import QuoteCard from './QuoteCard';

const MainQuotes = () => {
    const [quote1, setQuote1] = useState();

    useEffect(() => {
        await axios.get('https://quote-garden.herokuapp.com/api/v3/quotes/random').then((resp) => {
                setQuote1(resp.data.data[0]);
            });
        getQuote();
    }, []);

    return (
        <Row>
            <Col>
                <CardGroup>
                    <QuoteCard quoteData={quote1} />
                </CardGroup>
            </Col>
        </Row>
    );
};

export default MainQuotes;

Solution

  • Depending on the type of quote1 (I'm assuming it's a string) update to:

    const [quote1, setQuote1] = useState('')
    
    useEffect(() => {
      function fetchQuote() {
        await axios.get('https://quote-garden.herokuapp.com/api/v3/quotes/random')
        .then((resp) => {
          setQuote1(resp.data.data[0]);
        });
      }  
      if (!quote1) {
        fetchQuote();
      }
    }, []);
    

    Because the response from the API is a random quote, you have to handle it based on the value of quote1. This should work because quote1 will only be updated after the component mounts (when the value is an empty string), and the following render won't update state, so useEffect won't loop infinitely.

    Before the edit, I assumed the axios request was inside of the getQuote function. I have updated my answer to reflect the code you have posted.

    If the API response was static, because the items in the dependency array only cause a re-render if they are changed from their current value, it only causes a re render immediately after the first state update.