Reputation: 86
Expected to get data one time
How do I prevent the following error:
Too many re-renders. React limits the number of renders to prevent an infinite loop.'
I just changed a class based component to functional component and its not working
My source code
import React,{useState,useEffect} from "react";
// @material-ui/core components
import { makeStyles } from "@material-ui/core/styles";
// core components
import GridItem from "components/Grid/GridItem.js";
import GridContainer from "components/Grid/GridContainer.js";
import Table from "components/Table/Table.js";
import Card from "components/Card/Card.js";
import CardHeader from "components/Card/CardHeader.js";
import CardBody from "components/Card/CardBody.js";
import { db } from "../../firebase";
export default function TableList() {
const [state, setstate] = useState([])
var users = []
db.collection("users").get().then((snapshot)=>{
snapshot.forEach(doc => {
const data =doc.data()
users.push(data)
})
})
setstate(users)
console.log(state)
return (
<GridContainer>
<GridItem xs={12} sm={12} md={12}>
</GridItem>
<GridItem xs={12} sm={12} md={12}>
<Card plain>
<CardHeader plain color="primary">
<h4 className={classes.cardTitleWhite}>
Users
</h4>
<p className={classes.cardCategoryWhite}>
Here is a subtitle for this table
</p>
</CardHeader>
<CardBody>
<Table
tableHeaderColor="primary"
tableHead={["ID", "Name", "Country", "City", "Salary"]}
tableData={[
["1",
"Dakota Rice",
"$36,738",
"Niger",
"Oud-Turnhout"
]
]}
/>
</CardBody>
</Card>
</GridItem>
</GridContainer>
);
}
Upvotes: 0
Views: 153
Reputation: 7388
You get into a inifnite loop because you change the state while the component gets rendered so that triggers a othe reredner that changes the state and so on to inifnity. To resolve your problem put your state change into a useEffect
:
import React, { useState, useEffect } from "react";
// @material-ui/core components
import { makeStyles } from "@material-ui/core/styles";
// core components
import GridItem from "components/Grid/GridItem.js";
import GridContainer from "components/Grid/GridContainer.js";
import Table from "components/Table/Table.js";
import Card from "components/Card/Card.js";
import CardHeader from "components/Card/CardHeader.js";
import CardBody from "components/Card/CardBody.js";
import { db } from "../../firebase";
export default function TableList() {
const [state, setstate] = useState([]);
useEffect(() => {
var users = [];
db.collection("users")
.get()
.then((snapshot) => {
snapshot.forEach((doc) => {
const data = doc.data();
users.push(data);
});
});
setstate(users);
console.log(state);
}, []);
return (
<GridContainer>
<GridItem xs={12} sm={12} md={12}></GridItem>
<GridItem xs={12} sm={12} md={12}>
<Card plain>
<CardHeader plain color="primary">
<h4 className={classes.cardTitleWhite}>Users</h4>
<p className={classes.cardCategoryWhite}>
Here is a subtitle for this table
</p>
</CardHeader>
<CardBody>
<Table
tableHeaderColor="primary"
tableHead={["ID", "Name", "Country", "City", "Salary"]}
tableData={[
["1", "Dakota Rice", "$36,738", "Niger", "Oud-Turnhout"],
]}
/>
</CardBody>
</Card>
</GridItem>
</GridContainer>
);
}
This part }, []);
with the empty array at the end of the useEffect
says to it to run only when the component is rendered the first time. If you want the code in the useEffect
to be called also on other changes put some values in that array. Each time those values change the useEffect
will be called. Because we have an empty array the useEffect
will be called only once.
Upvotes: 2