Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

REACT JS - How to do a summation inside a map?

originally I was gonna ask how to call a function inside a map but I realize I wasn't doing anything wrong in the way I was calling my function so I just think that my code is wrong.

So I'm trying to do a summation of all the prices of a map i'm rendering sometimes those prices change due to the quantity that the person might want so I was calling:

//My function call inside the map
{calculateTotal(fixedPrice)}

//The function
const calculateTotal = (price) => {
        setTotalPrice (totalPrice + price)
      }

But I got this error in return

enter image description here

I don't understand how adding 2 numbers certain amount of times (in this case 9) would end up in an infinite loop. All I want to do is to sum all the prices into one variable and if the cantidad/quantity changes it add those changes too.

enter image description here

whole code in case you need it

import React, { useState, useEffect } from 'react'
import { auth, db } from './firebase';
import { useHistory } from 'react-router-dom';
import { Checkbox } from '@material-ui/core';

function CrearPedidos({user}) {
    const [libros, setLibros] = useState([]);
    const [cantidad, setCantidad] = useState( new Array(libros.length).fill(1));

    useEffect(()=>{
      setCantidad(new Array(libros.length).fill(1))
    }, [libros])

    const history = useHistory("");
    const [totalPrice, setTotalPrice] = useState();

    const librosRef = db.collection('libros');
    const queryRef = librosRef.where('grado', '==', '4° Grado');

    useEffect(() => {
        queryRef.orderBy("precio")
        .get()
        .then((snapshot) => {
              const tempData = [];
            snapshot.forEach((doc) => {

              const data = doc.data();
              tempData.push(data);
            });
            setLibros(tempData);
          });
      }, []);

      const mas = (index) => {
        setCantidad(cantidad[index]++);
        setCantidad([...cantidad])
      };

      const menos = (index) => {
        if (cantidad[index] > 0){
            setCantidad(cantidad[index]--);
            setCantidad([...cantidad])
        }
        else {
            window.alert("Sorry, Zero limit reached");
        }
      };

      const calculateTotal = (price) => {
        setTotalPrice (totalPrice + price)
      }

    return (
        <div className="listado_Pedidos"> 
        <div className="estudiantes_container">
            <h1 className = "estudiantes_container_h1">Estudiante: {user.displayName}</h1>
            <h1 className = "estudiantes_container_h1">Libros Nuevos</h1>
            <div className ="tableContainer">
            <table>
                <thead>
                    <tr className="Lista">
                        <th>Cantidad</th>
                        <th>Grado</th>
                        <th>Descripcion</th>
                        <th>Editorial</th>
                        <th>Precio</th>
                    </tr>
                </thead>
                <tbody>
                {libros.map((libros, index, fixedPrice) => (
                        <tr key={libros.id || index}>
                        <td>
                            <button onClick = {() => mas(index)}/>
                            {cantidad[index]}
                            {console.log(cantidad)}
                            <button onClick = {() => menos(index)}/>
                        </td>
                        <td>{libros.grado}</td>

                        <td >
                        <input onChange = {(event) => {
                            let checked = event.target.checked;
                        }} 
                        
                        type="checkbox" checked = "">
                        </input>
                        {libros.descripcion}
                        </td>

                        <td >{libros.editorial}</td>
                        <td >${fixedPrice = parseFloat(libros.precio).toFixed(2) * cantidad[index]}</td>
                        
                        {calculateTotal(fixedPrice)}
                        </tr>
                        
                     ))
                     }
                </tbody>
            </table>
            </div>

            <div className="space" />
            <button onClick="{realizarPedidos}" className = "crear_estudiante_boton">Realizar Pedidos</button>
            <div className="space" />
      </div>

      </div>
    )
}

export default CrearPedidos
like image 902
ReactPotato Avatar asked Dec 21 '25 10:12

ReactPotato


2 Answers

It's about two theoretical points.

  1. You must notice that map returns an array of values. So if you call a function, it will be call multiple times.

  2. In React, when state changes, component will re-render on every change. In map you call a function that changes state. Then state changing re-render all component. Again the map call that function , again and again. And this is an infinity loop.

If you want count total price, must do it outside of map return.

Separate logic. Do all countings outside of component return. Then in component return just show jsx elements

like image 69
Danial Avatar answered Dec 23 '25 00:12

Danial


As @Danial said, you're updating state so many times, very fastly, which triggers page renderization, and throw the error you got.

To do this summation of all items into the array, use reduce array function instead of map.

Reference: How to find the sum of an array of numbers

like image 40
Renan Felipe Ferreira Avatar answered Dec 22 '25 23:12

Renan Felipe Ferreira



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!