Bruno
Bruno

Reputation: 153

why do i get Error: Too many re-renders. React limits the number of renders to prevent an infinite loop

In my React.js code Im fetching from an API and I m getting this error Error: Too many re-renders. React limits the number of renders to prevent an infinite loop. PLEASE WHAT AM I DOING WRONG?

Here's my fetch component in App.js

    const App = () => {
  const [records, setRecords] = useState([])
  const [loading, setLoading] = useState({ loading: false })

  
  useEffect(() => {

    (async function() {
      try {
        setLoading(true)
        const res = await fetch('http://api.enye.tech/v1/challenge/records?limit=20&skip=0')
        const data  = await res.json();
        setRecords({ records: data})
        setLoading(false)
        console.log(data);
  
      } catch (err) {
        console.error(err);
      }
    })()
     
  }, []) 

      if(loading) {
        return <Preloader />
    }
  
    return (
      <Fragment>
        <SearchBar />
        <div className='container'>
          <Records loading={setLoading()} records={setRecords()} />
        </div>
      </Fragment>
    );
  }

And this is where I'm passing in the fetched data as props

const Records = ({ records, loading }) => {

    return (
        <div className={styles.p__container}>
        <div className="row">
            <div className="col-sm-8">
                <div className="py-3">
                    {records.length} Records
                </div>
            </div>
        </div>
        <div className={styles.p__grid}>
             {records.map(record => (
                 <RecordItem key={record.id} record={record} />
             ))
            }

        </div>
        <div className={styles.p__footer}>

        </div>
    </div>
    )

My integrated terminal shows no error but I get this error in my browser console enter image description here

Im also trying to see if I can fetch just 20 profiles from the API instead of 100

http://api.enye.tech/v1/challenge/records

Upvotes: 2

Views: 4376

Answers (3)

Mohammad Abdul Alim
Mohammad Abdul Alim

Reputation: 488

React has a property that whenever the value of states in a React component get updated, the component is re-rendered. Here you are passing the setLoading() and setRecords() as props to the Records component. You should pass records and loading instead. Every time setLoading() and setRecords() get updated, your component is re rendered and as a result an infinite loop of re rendering takes place.

Upvotes: 0

Rituraj Borpujari
Rituraj Borpujari

Reputation: 463

The error is in the line

<Records loading={setLoading()} records={setRecords()} />

By writing setLoading() and setRecords() you are essentially changing the states loading, and records. This ensures a re-render, since states are being changed

I believe, you are trying to pass the current loading status and records array as props to component Records. To do so, you should pass the values like

<Records loading={loading} records={records} />

That should clear out the too many re-renders error

Suggestion on useState usage

You are initializing the states loading and setRecords in a different way than the way you are using it later.

For eg., you initialize loading as {loading: false} but later call setLoading(false). You should initialize the loading state as a boolean state using

const [loading, setLoading] = useState(false);

// example usage
setLoading(true);

Similarly, for records, you are initializing with an empty array useState([]), but later setting records state as an object using setRecords({ records: data})

You should use either one of the approaches

/** Approach 1 (Array typed) */
const [records, setRecords] = useState([]);

// example usage
setRecords(data);

/** Approach 2 (Object typed) */
const [records, setRecords] = useState({records: []});

// example usage
setRecords({records: data});

Upvotes: 0

Nick
Nick

Reputation: 16596

It's likely here, when you call setLoading() and setRecords on every render:

<Records loading={setLoading()} records={setRecords()} />

You probably just want to pass a the loading and records variables:

<Records loading={loading} records={records} />

Upvotes: 1

Related Questions