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

Time:10-06

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;

CodePudding user response:

Can we get your entire code please? It seems the problem is going to be with your state hook and figuring out exactly what its doing.

My guess as of now is your state hook "setQuote1" is being invoked in a way that causes a re-render, which then would invoke your useEffect() again (as useEffect runs at the end of the render cycle) and thus, calling upon your setQuote1 hook again. This repeats itself indefinitely.

useEffect() allows for dependencies and gives you the power to tell exactly when useEffect() should be invoked.

Example: useEffect(() { code here }, [WATCH SPECIFICALLY THIS AND RUN ONLY WHEN THIS UPDATES]).

When you leave the dependency array empty, you tell the hook to run whenever ANYTHING updates state. This isn't necessarily bad but in some cases you only want your useEffect() to run when a specific state updates.

Something in your application must be triggering your useEffect() hook to run when you aren't wanting it to.

CodePudding user response:

Depending on the type of quote1 (I'm assuming it's a string) change the line that initializes the state of quote1 to:

const [quote1, setQuote1] = useState('')

then change useEffect to

if (!quote1) {
  getQuote()
}

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

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.

  • Related