0

I am trying to use two class based components <Cities> and <Hospital> in another component.

I am getting an error :-

Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

I am trying to create 4 buttons that will display those hospitals with city whose button is clicked.

import React,{ Component } from 'react';
import Hospital from './hospital/hospital'
import Cities from '../sidebarcomp/cities'
class Hospitals extends Component {
state = {
    hospitals: [
      { id: 1, status: false, name: 'Apollo Hospital', city: 'Chennai', bedtype1: 500, bedtype2: 800, bedtype3: 1300,bed1av: 60, bed2av: 40, bed3av: 20, },
      { id: 2, status:false, name: 'Fortis Hospital', city: 'New Delhi', bedtype1: 600, bedtype2: 1000, bedtype3: 1400, bed1av: 60, bed2av: 40, bed3av: 20,  },
      { id: 3, status: true, name: 'Tata Memorial Hospital', city: 'Mumbai', bedtype1: 400, bedtype2: 800, bedtype3: 1200, bed1av: 60, bed2av: 40, bed3av: 20,  },
      { id: 4, status: true,name: 'Lilavati Hospital', city: 'Pune', bedtype1: 500, bedtype2: 900, bedtype3: 1300, bed1av: 60, bed2av: 40, bed3av: 20,  }
    ],
};

render() {
    return(
      <React.Fragment>
        <Cities
         hospitals={this.state.hospitals}
        /> 

        {this.state.hospitals.map((hospital, index) => {
        if(hospital.status){
        return (
        <Hospital
          name={hospital.name}
          bed1av={hospital.bed1av}
          bed2av={hospital.bed2av}
          bed3av={hospital.bed3av}
          key={hospital.id}
        />
      )};
        })}
        </React.Fragment>
    )
}
}

export default Hospitals;

Cities.js

import React,{ Component } from 'react';

class Cities extends Component {
nameChangedHandler = (id) => {
    const hospitalIndex = this.props.hospitals.findIndex(p => {
      return p.id === id;
    });

    const hospital = {
      ...this.props.hospitals[hospitalIndex]
    };

    // const person = Object.assign({}, this.state.persons[personIndex]);

    hospital.status = true;

    const hospitals = [...this.props.hospitals];
    hospitals[hospitalIndex] = hospital;

    this.setState((prevState,props) =>{
        return {
         hospitals: hospitals
        };
    });
  }

render(){
    return(
    <div>
        <button onclick={this.nameChangedHandler(1)}>Chennai</button>
        <button onclick={this.nameChangedHandler(3)}>Mumbai</button>
        <button onclick={this.nameChangedHandler(4)}>Pune</button>
        <button onclick={this.nameChangedHandler(2)}>New Delhi</button>
    </div>
)
}

}
export default Cities;
Rohit Ambre
  • 921
  • 1
  • 11
  • 25

3 Answers3

2

The issue is that you are calling the setState function inside the Cities component.

What you should do instead is pass the nameChangedHandler as a prop to the Cities component so it updates the state from the parent component (Hospitals)

class Hospitals extends Component {
    nameChangeHandler = (id) => {
        ....
    }
    ...
    <Cities nameChangedHandler={this.nameChangedHandler}/> 

and in Cities.js

class Cities extends Component {
   // remove nameChangeHandlerFunction

   render(){
    return(
      <div>
        <button onClick={this.props.nameChangedHandler(1)}>Chennai</button>
        <button onClick={this.props.nameChangedHandler(3)}>Mumbai</button>
        <button onClick={this.props.nameChangedHandler(4)}>Pune</button>
        <button onClick={this.props.nameChangedHandler(2)}>New Delhi</button>
      </div>
      )
    }
Alam Téllez
  • 178
  • 9
  • This will lead to the same problem... it should be an arrow function `button onclick=() => {this.props.nameChangedHandler(1)` – SakoBu Jul 29 '20 at 05:58
  • You should also use `onClick` instead of `onclick` – Alam Téllez Jul 29 '20 at 06:04
  • 1
    You should update your answer with my suggestion - this will lead to the same problem as he is invoking the function in the `onClick` and not using it as a callback... – SakoBu Jul 29 '20 at 06:07
1

You have to use handler like:

nameChangedHandler = (id) => () => {

For further detail, read my another post

Bhojendra Rauniyar
  • 83,432
  • 35
  • 168
  • 231
0

I think it might be because you have the console.log in the render like that. i suggest you put it in the return if you really need it.

Davia
  • 73
  • 10