Shruti Jain
Shruti Jain

Reputation: 11

too many re-renders. react limits the number of renders to prevent an infinite loop. UseEffect

Whenever I try to render my component, I am getting this error :

too many re-renders. react limits the number of renders to prevent an infinite loop.

I have tried using axios cancelToken and square brackets in useEffect hook. But nothing works. The code requests an array of notifications from server and store it in a state variable "notifications", using useState react hook. Here's my code:

import React, {useState, useEffect} from 'react';
import NavbarComponent from './NavbarComponent';
import { Card, Button, Modal } from "react-bootstrap";
import axios from 'axios';

function Notifications({username}) {
  const [show, setShow] = useState(false);
  const [response, setresponse] = useState([])
  const handleClose = () => setShow(false);
  const handleShow = () => setShow(true);
  const [notifications, setnotifictions] = useState([])
  const [password, setpassword] = useState("")
  var user = {
    username: username
  }
  const CancelToken = axios.CancelToken;
  const source = CancelToken.source();

  useEffect(() => {
    const fetchnoti = async () => {
      await axios.post('/api/getnoti', user, {cancelToken: source.token})
        .then(res => {
          console.log(res)
          setnotifictions(res.data)
        })
        .catch(err => {
          if (axios.isCancel(err)) {
            console.log('Request canceled', err.message);
          }
          else console.log(err)
        })
      
    }
    
    fetchnoti();

    return () => {
        source.cancel()
    }
  }, [])
  
  
  function accept(noti){
    var param = {
      noti: noti,
      password: password
    }
    axios.post('/api/accepttxn', param)
      .then(res => {
        console.log(res)
        setresponse(res.data)
      })
      .catch(err => {
        console.log(err)
      })
  }

  function accepttxn(noti){
    handleShow(); 
            
            
            setresponse([]); 
            setpassword("");
    return(
      <div>

        <Modal show={show} onHide={handleClose}>
          <Modal.Header closeButton>
            <Modal.Title>Enter Password to Proceed</Modal.Title>
          </Modal.Header>
          <Modal.Body><input type="password" value={password} onChange={(event) => setpassword(event.target.value)}/></Modal.Body>
          <Modal.Footer>
            <Button variant="secondary" onClick={handleClose}>
              Close
            </Button>
            <Button variant="success" onClick={() => {accept(noti)}}>
              Proceed to Accept
            </Button>
            {response}
          </Modal.Footer>
        </Modal>
      </div>
    );
  }

  function reject(noti){
    var param = {
      noti: noti,
      password: password
    }
    axios.post('/api/rejecttxn', param)
      .then(res => {
        console.log(res)
        setresponse(res.data)
      })
      .catch(err => {
        console.log(err)
      })
  }

  function rejecttxn(noti){
    handleShow();
            
            
    setresponse([]); 
    setpassword("");
    return(
      <div>

        <Modal show={show} onHide={handleClose}>
          <Modal.Header closeButton>
            <Modal.Title>Enter Password to Proceed</Modal.Title>
          </Modal.Header>
          <Modal.Body><input type="password" value={password} onChange={(event) => setpassword(event.target.value)}/></Modal.Body>
          <Modal.Footer>
            <Button variant="secondary" onClick={handleClose}>
              Close
            </Button>
            <Button variant="danger" onClick={() => {reject(noti)}}>
              Proceed to Reject
            </Button>
            {response}
          </Modal.Footer>
        </Modal>
      </div>
    );
    
  }

  const notis = notifications.map((noti) => {
    return(
      <Card key={noti.id}>
        <Card.Body>
          <Card.Text>
            Sender: {noti.sender}
          </Card.Text>
          <Card.Text>
            Amount: {noti.amount}
          </Card.Text>
          <Card.Text>
            {noti.message ? <div>Message: {noti.message}</div> : null}
          </Card.Text>
          <Button variant="primary" 
          onClick={
             
            accepttxn(noti)
            
            
            
          }>Accept</Button>
          <Button variant="danger" 
          onClick={
            
            rejecttxn(noti)
            
            
            
          }>Reject</Button>

        </Card.Body>
      </Card>
    )

  })

  return (
    <div>
      {notis.length ? <div>{notis}</div> : <h1>No new notifications</h1>}
    </div>
  );
}

export default Notifications;

Can anyone help me out?

Upvotes: 0

Views: 166

Answers (1)

JustinCredible
JustinCredible

Reputation: 165

It's not the useEffect probably, you have a button which calls a function whenever it renders:

<Button variant="danger" onClick={rejecttxn(noti)}>Reject</Button>

You could rewrite the function to return a function, it improves performance because you may re-render components that does not need to be rerendered when using inline functions, check below example:

function rejecttxn(noti){
    return function() {
    handleShow();
            
            
    setresponse([]); 
    setpassword("");
    return (
      <div>

        <Modal show={show} onHide={handleClose}>
          <Modal.Header closeButton>
            <Modal.Title>Enter Password to Proceed</Modal.Title>
          </Modal.Header>
          <Modal.Body><input type="password" value={password} onChange={(event) => setpassword(event.target.value)}/></Modal.Body>
          <Modal.Footer>
            <Button variant="secondary" onClick={handleClose}>
              Close
            </Button>
            <Button variant="danger" onClick={() => {reject(noti)}}>
              Proceed to Reject
            </Button>
            {response}
          </Modal.Footer>
        </Modal>
      </div>
    );
   } 
  }

Or using arrow functions:

const rejecttxn = (noti) => () => {
    handleShow();


    setresponse([]); 
    setpassword("");
    return (
      <div>

        <Modal show={show} onHide={handleClose}>
          <Modal.Header closeButton>
            <Modal.Title>Enter Password to Proceed</Modal.Title>
          </Modal.Header>
          <Modal.Body><input type="password" value={password} onChange={(event) => setpassword(event.target.value)}/></Modal.Body>
          <Modal.Footer>
            <Button variant="secondary" onClick={handleClose}>
              Close
            </Button>
            <Button variant="danger" onClick={() => {reject(noti)}}>
              Proceed to Reject
            </Button>
            {response}
          </Modal.Footer>
        </Modal>
      </div>
    );
   } 
  }

Upvotes: 0

Related Questions