soufiane_ben_yaala
soufiane_ben_yaala

Reputation: 86

Too many re-renders. React limits the number of renders to prevent an infinite loop?

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

Answers (1)

Tarik Huber
Tarik Huber

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

Related Questions