error: Maximum update depth exceeded

1

Hi, I am trying to capture a variable in a child component and pass it to the parent component App.js to update the total amount status. This is the error message:

"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."

Next I put the components that interact in the process:

App.js

  class App extends Component {
  constructor() {
   super();
   this.state = {
   categorias: {},
   productos: {},
   productosOrden: {},
   orden: {},
   total: 0,
   montoTotal: 0};
   }
   totalMonto = (valor) =>{
     console.log(valor);
    const montoTotal = valor;
     this.setState({montoTotal});
     }

 render() {
   return (
    <div className="App">
    <div className="row">

      <PedidoTotal 
      {...this.state}
      titulo="Pedido Total" 
      totalMonto={this.totalMonto} 
      />
      <CalcularVuelto titulo="Calcule el Cambio"
      totalMonto={this.totalMonto} 
      />
    </div>
  </div>  
);}

----- Total Order component

 class PedidoTotal extends Component{
 renderOrden = (key) =>{
 const productos = this.props.productosOrden;
 console.log(productos);
 const prod = this.props.productosOrden[key];
 const count = this.props.orden[key];
 //this.props.actualizarMonto();
 return <li key={key}>
 {count}: unidades de {prod.nombre}
 :${count * prod.precio}
 <button onClick={()=>this.props.deleteOrden(key)}>eliminar</button>
 <button onClick={()=>this.props.reduceOrden(key)}>Reducir</button>
 </li>
 }
 render(){
    const ordenIds = Object.keys(this.props.orden);
    //Calculando el total a pagar
      const total = ordenIds.reduce((prevTotal, key)=>{
        const prod = this.props.productosOrden[key];
        const count = this.props.orden[key];
        return prevTotal + (count * prod.precio)
    }, 0);
    this.props.totalMonto(total);  
    return(
    <div className="col-md-3">
        <h3>{this.props.titulo}</h3>
        <ul>
            {ordenIds.map(this.renderOrden)}
        </ul>
        <h5>Total a pagar: ${total} </h5>
    </div>
    );
   }
  }
    
asked by user3821102 24.07.2018 в 01:44
source

2 answers

1

Hello friends, the answer to my problem was to implement the calculation of the total amount to be paid in the same totalMonto function and thus avoid the loop:

totalMonto = () =>{
  const ordenIds = Object.keys(this.state.orden);
//Calculando el total a pagar
  const total = ordenIds.reduce((prevTotal, key)=>{
  const prod = this.state.productosOrden[key];
  const count = this.state.orden[key];
  return prevTotal + (count * prod.precio)
  }, 0);
  console.log(total);
 return total; 
 }
    
answered by 24.07.2018 в 02:08
0

So that this does not happen to you again and the following should be mentioned.

You should never mutate the state inside the render function, the reason is because the render function is executed automatically in these three scenarios:

  • The state / state has been mutated using the .setState () function of the component.

  • The properties / props have been mutated by a component in a higher hierarchy

  • Invoking the .forceUpdate () function of the component, this causes the component to be rendered again regardless of whether there is no mutation in the state or props.

  • So if for some reason you mutate the state inside the render () function, you are causing a second execution of that function and this in turn will carry a third call and so on, causing an infinite loop.

    That's exactly what you're doing in the PedidoTotal component but in your case the infinite loop is given by a combination of the first and second scenarios.

    Your component hierarchy is

    App
      -> PedidoTotal
    

    Your loop occurs when in the render function of the component PedidoTotal you execute the following line this.props.totalMonto(total) , where totalMonto is a function of the upper component App that you expose it to the lower hierarchical level component through of props , in the implementation of this function is where the problem is.

    totalMonto = (valor) =>{
        console.log(valor);
        const montoTotal = valor;
        this.setState({montoTotal});
    }
    

    and that is mutating the state in the final line by invoking this.setState({montoTotal}); this will cause the state of App mute and therefore execute the function render of the component App which in turn will cause that the function render of the component PedidoTotal is again executed and so on, leading to an infinite loop.

    PedidoTotal.render() -> App.totalMonto() -> App.render() -> PedidoTotal.Render() -> App.totalMonto() -> App.render() -> PedidoTotal.render() -> App.totalMonto() -> App.render()... etc.
    

    What really solved your problem was that you later removed the this.setState({montoTotal}); of the totalMonto of the App component, by doing so you broke the infinite loop solving the problem.

        
    answered by 26.07.2018 в 19:51