skip to Main Content

Great day everyone, I’m still new to React and I stumble upon this problem. I’ve done prompt engineering to compose this code. My goal here is to pass data from a component called NumberOfKilos to the SMSForm which will receive the data passed and display them in the Summary Card React bootstrap component. I’ve spent countless hours to figure out how to solve it but i did not come to one. If you would be so kind to help me. Big thanks.

error message at browser console:
Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn’t have a dependency array, or one of the dependencies changes on every render.

SMSForm component (the child)

import NumberOfKilos from "../Components/NumberOfKilosCard";
import { Row, Col, Container, Form, Card } from 'react-bootstrap';
import { useState } from "react";

function SMSForm() {
  const [kilosData, setKilosData] = useState({
    numKilosSale: 0,
    numKilosCredit: 0,
    totalKilos: 0,
    cashSales: 0,
    creditSales: 0,
    totalSales: 0,
  });

  // Function to update kilos data
  const handleKilosData = (data) => {
    setKilosData(data);
  };

  return (
    <Container fluid>
      <Row>
        <Col>
          <NumberOfKilos handleKilosData={handleKilosData} />
        </Col>


        <Col md={3}>
          <Form>
            <Card>
              <Card.Header className='bg-dark text-light ' as="h4">
                Summary
              </Card.Header>

              <Row className='mx-3 mt-3'>
                <Col>
                  <Form.Label>Number of Kilos (Sale):</Form.Label>
                </Col>
                <Col xs={4}>
                  {kilosData.numKilosSale}
                </Col>
              </Row>

              <Row className='mx-3 mt-3'>
                <Col>
                  <Form.Label>Number of Kilos (Credit):</Form.Label>
                </Col>
                <Col xs={4}>
                  {kilosData.numKilosCredit}
                </Col>
              </Row>

              <Row className='mx-3 mt-3'>
                <Col>
                  <Form.Label>Total Kilos:</Form.Label>
                </Col>
                <Col xs={4}>
                  {kilosData.totalKilos}
                </Col>
              </Row>

              <Row className='mx-3 mt-3'>
                <Col>
                  <Form.Label>Cash Sales:</Form.Label>
                </Col>
                <Col xs={4}>
                  {kilosData.cashSales}
                </Col>
              </Row>

              <Row className='mx-3 mt-3'>
                <Col>
                  <Form.Label>Credit Sales:</Form.Label>
                </Col>
                <Col xs={4}>
                  {kilosData.creditSales}
                </Col>
              </Row>

              <Row className='mx-3 mt-3'>
                <Col>
                  <Form.Label>Total Sales:</Form.Label>
                </Col>
                <Col xs={4}>
                  {kilosData.totalSales}
                </Col>
              </Row>

             
            </Card>
          </Form>
        </Col>
      </Row>
    </Container >
  );
}

export default SMSForm;

NumberOfKilos component (the parent, the one who will passed the data)

import React, { useState, useEffect, useCallback } from 'react';
import { Container, Row, Col, Form, Button, Card } from 'react-bootstrap';
import { FiTrash } from 'react-icons/fi';

function NumberOfKilos({ handleKilosData }) {
  const [numKilosRow, setNumKilosRow] = useState([
    { product: '', kilosSold: '', productSales: '', paymentStat: '' },
  ]);

  const handleAddNumKilosRow = () => {
    setNumKilosRow([...numKilosRow, { product: '', kilosSold: '', productSales: '', paymentStat: '' }]);
  };

  const handleDeleteNumKilosRow = (index) => {
    if (numKilosRow.length > 1) {
      const updatedKilosRows = [...numKilosRow];
      updatedKilosRows.splice(index, 1);
      setNumKilosRow(updatedKilosRows);
    }
  };

  const handleNumKilosChange = (value, index, field) => {
    const updatedKilosRows = [...numKilosRow];
    updatedKilosRows[index][field] = value;
    setNumKilosRow(updatedKilosRows);
  };

  const calculateKilosData = useCallback(() => {
    let saleKilosSum = 0;
    let creditKilosSum = 0;
    let cashSalesSum = 0;
    let creditSalesSum = 0;

    numKilosRow.forEach((row) => {
      if (row.paymentStat === 'Sale') {
        if (row.kilosSold) saleKilosSum += parseFloat(row.kilosSold);
        if (row.productSales) cashSalesSum += parseFloat(row.productSales);
      } else if (row.paymentStat === 'Credit') {
        if (row.kilosSold) creditKilosSum += parseFloat(row.kilosSold);
        if (row.productSales) creditSalesSum += parseFloat(row.productSales);
      }
    });

    const kilosDataObject = {
      numKilosRow,
      numKilosSale: saleKilosSum,
      numKilosCredit: creditKilosSum,
      cashSales: cashSalesSum,
      creditSales: creditSalesSum,
      totalKilos: saleKilosSum + creditKilosSum,
      totalSales: cashSalesSum + creditSalesSum,
    };

    handleKilosData(kilosDataObject);
  }, [numKilosRow, handleKilosData]);

  useEffect(() => {
    calculateKilosData();
  }, [calculateKilosData]);

  return (
    <Container>
      <Form>
        <Row className='mb-3'>
          <Col>
            <Card style={{ height: '250px', overflow: 'auto' }}>
              <Card.Header as='h4' className='bg-dark text-light' style={{ position: 'sticky', top: '0', zIndex: '1' }}>
                Number of Kilos
              </Card.Header>

              <Row className='mx-3 mt-3'>
                <Col>
                  <Form.Label>Product</Form.Label>
                </Col>

                <Col>
                  <Form.Label>Payment Status</Form.Label>
                </Col>

                <Col>
                  <Form.Label>Kilos Sold</Form.Label>
                </Col>

                <Col>
                  <Form.Label>Product Sale</Form.Label>
                </Col>

                <Col xs={1}></Col>
              </Row>

              {numKilosRow.map((row, index) => (
                <Row className='mx-3' key={index}>
                  <Col>
                    <Form.Group className='mb-3' controlId={`productSelection${index}`}>
                      <Form.Select value={row.product} onChange={(e) => handleNumKilosChange(e.target.value, index, 'product')}>
                        <option>Select a product</option>
                        <option value='Fish'>Fish</option>
                        <option value='Squid'>Squid</option>
                        <option value='Octopus'>Octopus</option>
                        <option value='Cuttlefish'>Cuttlefish</option>
                        <option value='Cogita'>Cogita</option>
                      </Form.Select>
                    </Form.Group>
                  </Col>

                  <Col>
                    <Form.Select value={row.paymentStat} onChange={(e) => handleNumKilosChange(e.target.value, index, 'paymentStat')}>
                      <option>Select Status</option>
                      <option value='Sale'>Sale</option>
                      <option value='Credit'>Credit</option>
                    </Form.Select>
                  </Col>

                  <Col>
                    <Form.Group className='mb-3' controlId={`kilosSold${index}`}>
                      <Form.Control type='number' placeholder='Enter kilos sold' value={row.kilosSold} onChange={(e) => handleNumKilosChange(e.target.value, index, 'kilosSold')} />
                    </Form.Group>
                  </Col>

                  <Col>
                    <Form.Group className='mb-3' controlId={`productSales${index}`}>
                      <Form.Control type='number' placeholder='Enter sale' value={row.productSales} onChange={(e) => handleNumKilosChange(e.target.value, index, 'productSales')} />
                    </Form.Group>
                  </Col>

                  <Col xs={1}>
                    {numKilosRow.length > 1 && (
                      <Button variant='outline-danger' onClick={() => handleDeleteNumKilosRow(index)}>
                        <FiTrash />
                      </Button>
                    )}
                  </Col>
                </Row>
              ))}

              <Row className='mx-3 mb-3'>
                <Col>
                  <Button variant='primary' onClick={handleAddNumKilosRow}>
                    + Add Another Row
                  </Button>
                </Col>
              </Row>
            </Card>
          </Col>
        </Row>
      </Form>
    </Container>
  );
}

export default NumberOfKilos;

I’ve tried using callback as well as useRef which is suggested by the AI. but it did not help.

2

Answers


  1. This error happens when the code is trapped in a loop hole and causes too much rerender. The second argument of the useEffect is the problem because useCallback returns a different function every time the component renders and the useEffect runs again and again.

    You can solve this by removing the second argument like this:

    useEffect(() => {
       calculateKilosData();
    }, []);
    

    Also this causes a warning in the console and if you want to prevent that warning you can move your calculateKilosData function definition in to the useEffect hook.

    Login or Signup to reply.
  2. The warning you’re encountering is related to an infinite loop caused by the dependency array in your useEffect hook in the NumberOfKilos component. The calculateKilosData function is defined inside the component and referenced in the dependency array, causing the useEffect to trigger a re-render and create an infinite loop.

    To resolve this issue, you can move the calculateKilosData function outside the component and pass it as a dependency to the useEffect hook.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search