Reputation: 153
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
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
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
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
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