hoozr
hoozr

Reputation: 463

Infinity loop after componentDidUpdate() in ReactJS

I have React JS app, which updating boostrap grid table with entries from ASP .NET Core Web API.

And I need to update the grid with new entries after inserting. I did that with help of componentDidUpdate() and using refreshList() function there, but I am getting an infinity loop of refreshList() function.

enter image description here

Any thoughts about how to update the grid without that loop?

import React, {Component} from 'react';
import {Table, Container} from 'react-bootstrap';
import {Button, ButtonToolbar} from 'react-bootstrap';

import {AddDepModal} from './AddDepModal';
import {EditDepModal} from './EditDepModal';

export class Department extends Component {

    constructor(props){
        super(props);
        this.state = {deps:[], addModalShow: false, editModalShow: false}
    }

    componentDidMount()
    {
        this.refreshList();
    }
    refreshList()
    {
       fetch("https://localhost:5001/api/departments")
       .then(response=> response.json())
       .then(data=> { 
        this.setState({deps:data});
       });
    }

    componentDidUpdate()
    {
        this.refreshList();
    }

    render(){

     const {deps, depid, depname} = this.state;
     let addModalClose = () => this.setState({addModalShow:false})
     let editModalClose = () => this.setState({editModalShow:false})
    return (
        <div>
     <Table className = "mt-4" striped bordered hover size ="sm">
    <thead>
        <tr>
            <th>DepartmentID</th>
            <th>DepartmentName</th>
            <th>Options</th>
        </tr>
    </thead>
    <tbody>
        {deps.map(dep=> 
            <tr key = {dep.id}> 
            <td>{dep.id}</td>
            <td>{dep.name}</td>
            <td>
                <ButtonToolbar>
                    <Button
                    className ="mr-2" variant ="info"
                    onClick = {() => this.setState({editModalShow:true, depid: dep.id, depname: dep.name})}
                    >
                        Edit
                    </Button>
                    <EditDepModal
                    show = {this.state.editModalShow}
                    onHide = {editModalClose}
                    depid = {depid}
                    depname = {depname}/>
                </ButtonToolbar>
            </td>
            </tr>
            )}
    </tbody>
     </Table>
     <ButtonToolbar>
    <Button variant = "primary" onClick = {() => this.setState({addModalShow: true})}>Add Department</Button>
    <AddDepModal 
    show ={this.state.addModalShow} 
    onHide ={addModalClose}/>
</ButtonToolbar>
</div>
    )
    }
}

Upvotes: 0

Views: 279

Answers (3)

David
David

Reputation: 1154

Remove componentDidUpdate() because refreshData doesn't depend from props to fetch data and there aren't any checks with prevProps and newProps.

You can call refreshData method from Add or Save Button callback.

I image that you are saving data from modal code, add setState callback.

Modal save data, onhide set show state to false and call refreshData from once.

let addModalClose = () => this.setState({addModalShow:false}, this.refreshData)

Upvotes: 2

ABGR
ABGR

Reputation: 5205

You're calling this.refreshList(); which does some thing and then set the state. After the state is set, render functions is called and in turn componentDidUpdate is called again, setting the infinite loop. To make it work, compare from the previous props and then call the this.refreshList(); if needed.

componentDidUpdate(prevProps) {
  // Typical usage (don't forget to compare props):
  if (this.props.depid !== prevProps.depid) { //Replace `depid` with the props you like to compare changes. If that is changed, then only call
    this.refreshList();
  }
}

You may call setState() immediately in componentDidUpdate() but note that it must be wrapped in a condition like in the example above, or you’ll cause an infinite loop. It would also cause an extra re-rendering which, while not visible to the user, can affect the component performance. If you’re trying to “mirror” some state to a prop coming from above, consider using the prop directly instead. Read more about why copying props into state causes bugs.

see the docs: https://reactjs.org/docs/react-component.html#componentdidupdate

Upvotes: 2

Marco
Marco

Reputation: 1620

The problem is you are calling refreshList in componentDidMount and componentDidUpdate. As described in the documentation: https://reactjs.org/docs/react-component.html#componentdidupdate

you should at some condition to avoid an infinity loop in componentDidUpdate.

Upvotes: 1

Related Questions