Search code examples
javascriptreactjsreduxstatesetstate

Cannot update a component (`App`) while rendering a different component (`AddBudgetModal`). To locate the bad setState() call inside `AddBudgetModal`


Below code is from App.jsx

I am trying to open a addbudgetmodal line:44 by passing true-false, getting error "Cannot update a component (App) while rendering a different component (AddBudgetModal). To locate the bad setState() call inside AddBudgetModal".

import { Container, Stack, Button } from "react-bootstrap";
import BudgetCard from "./BudgetCard";
import AddBudgetModal from "./AddBudgetModal";
import { useState } from "react";


function App() {

  const [isopen, setOpen]= useState(false)
  function showAddModal(){
    console.log("click")
    setOpen(true)
  }
  function handleClose(){
    setOpen(false)
  }
  return (
    <>
    <Container className="my-4">
      <Stack direction="horizontal" gap={2} className="mb-4">
        <h1 className="me-auto">Budget App</h1>
        <Button className="" variant="primary" onClick={showAddModal}>
          Add Budget
        </Button>
        <Button className="" variant="outline-danger">
          Add Expense
        </Button>
      </Stack>
      <div
        style={{
          display: "grid",
          gridTemplateColumns: "repeat(auto-fill,minmax(300px,1fr))",
          gap: "1rem",
          alignItems: "flex-start",
        }}
      >
        <BudgetCard name="Chocolates" amount="60" maxamount="100" />
        <BudgetCard name="Chocolates" amount="60" maxamount="100" />
        <BudgetCard name="Chocolates" amount="60" maxamount="100" />

        <BudgetCard name="Chocolates" amount="60" maxamount="100" />
      </div>
    </Container>
    <AddBudgetModal show={isopen} handleClose={handleClose}/>
    </>
  );
}

And here is my AddBudgetModal

import React, { useRef } from 'react'
import { Modal,Form, Button} from 'react-bootstrap'
import { useBudget } from './context/BudgetContext'

export default function AddBudgetModal({show, handleClose}) {
const nameref= useRef()
const maxref= useRef()
 const {addBudget}= useBudget()




    function handleSubmit(e){
      e.preventDefault()

addBudget( {
        name:nameref.current.value,
        maxamount: parseFloat(maxref.current.value)
      })
      handleClose()
    }
  return (
<Modal show= {show} onHide={handleClose()}>
    <Form onSubmit={handleSubmit}>
        <Modal.Header closeButton>
            <Modal.Title>New Budget</Modal.Title>
        </Modal.Header>
        <Modal.Body>
            <Form.Group className='mb-3' controlId='name'>
                <Form.Label>Name</Form.Label>
                <Form.Control ref={nameref} type='text' required/>
            </Form.Group>
            <Form.Group className='mb-3' controlId='maxamount'>
                <Form.Label>Maximum Spending</Form.Label>
                <Form.Control ref={maxref} type='number' required min={0}/>
            </Form.Group>
            <div className='d-flex justify-content-end'>
            <Button variant="success" type='submit'>Add</Button>
            </div>
        </Modal.Body>

    </Form>

</Modal>
  )
}

I am using state to toggle between true and false, i cannot figure out whats happening.


Solution

  • The error is in the AddBudgetModal component, When you use the Modal, you have to pas the handleclose as a prop, you are calling the fuction, you have to do the next change:

    <Modal show= {show} onHide={handleClose}>// Remove the (), you dont have to call the function 
    <Form onSubmit={handleSubmit}>
        <Modal.Header closeButton>
            <Modal.Title>New Budget</Modal.Title>
        </Modal.Header>
        <Modal.Body>
            <Form.Group className='mb-3' controlId='name'>
                <Form.Label>Name</Form.Label>
                <Form.Control ref={nameref} type='text' required/>
            </Form.Group>
            <Form.Group className='mb-3' controlId='maxamount'>
                <Form.Label>Maximum Spending</Form.Label>
                <Form.Control ref={maxref} type='number' required min={0}/>
            </Form.Group>
            <div className='d-flex justify-content-end'>
            <Button variant="success" type='submit'>Add</Button>
            </div>
        </Modal.Body>
    
    </Form>