1

I'm trying to trigger a modal from inside a child component but am getting the following error.

Too many re-renders error enter image description here

My code for the parent and child component are below:

Onboard.jsx

import React from 'react'
import { Row } from 'react-bootstrap'

import { PersonalDetails } from './personalDetails'
import { EmailVerification } from './emailVerification'
import { Form } from './form'
import { FAQs } from './faq'
import { LeftCol, RightCol } from './styles'
import { Modal, Button } from 'react-bootstrap'

const OnboardPage = props => {
    const [show, setShow] = React.useState(false);
    const handleShow = (showValue) => setShow(showValue);

    return (
        <Row>
            <LeftCol md={8}>
                <PersonalDetails parentShowFn={handleShow}/>
                <Form />
            </LeftCol>
            <RightCol md={4}>
                <EmailVerification />
                <FAQs />
            </RightCol>
            <Modal show={show} onHide={handleShow(false)}>
                <Modal.Header closeButton>
                  <Modal.Title>Modal heading</Modal.Title>
                </Modal.Header>
                <Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
                <Modal.Footer>
                  <Button variant="secondary" onClick={handleShow(false)}>
                    Close
                  </Button>
                  <Button variant="primary" onClick={handleShow(false)}>
                    Save Changes
                  </Button>
                </Modal.Footer>
            </Modal>
        </Row>
    )
}

export default OnboardPage

Personaldetails.jsx

import React from 'react'

import { colors } from '../../../../res'
import { TitleText, CommonText, SubHeadingText } from '../../../commons/freelancer/texts'
import { Container, TitleRow, DetailsRow, DetailsItem, EditBtn } from './personalDetailsStyles'
import { Modal, Button } from 'react-bootstrap'
// import EditDetailsModal from './EditDetailsModal'

const PersonalDetails = ({parentShowFn}) => {

    return (

        <Container>
        <TitleRow>
            <TitleText>Personal Details</TitleText>
            <EditBtn onClick={() => parentShowFn(true)}>Edit</EditBtn>
        </TitleRow>
        </Container>
    )

}
    

export default PersonalDetails

I think it might be because some render function is getting called infinitely but I can't seem to fix the error.

Alireza
  • 2,319
  • 2
  • 23
  • 35
  • Does this answer your question? [Uncaught Invariant Violation: Too many re-renders. React limits the number of renders to prevent an infinite loop](https://stackoverflow.com/questions/55265604/uncaught-invariant-violation-too-many-re-renders-react-limits-the-number-of-re) – shreyasm-dev Sep 12 '20 at 15:33
  • 1
    Your button click handlers are wrong. They *call* your handleShow function every render, which triggers a rerender ad infinitum. You don't even need handleShow. Change your click handlers to `() => setShow(true)` or false. – Jared Smith Sep 12 '20 at 15:34

2 Answers2

2

Problem is in Onboard.js, pass the function in React component like ()=>handleShow(false) or handleShow, because function was not bind on particular event, it was getting called each time on render, It should be like this

import React from 'react'
import { Row } from 'react-bootstrap'

import { PersonalDetails } from './personalDetails'
import { EmailVerification } from './emailVerification'
import { Form } from './form'
import { FAQs } from './faq'
import { LeftCol, RightCol } from './styles'
import { Modal, Button } from 'react-bootstrap'

const OnboardPage = props => {
    const [show, setShow] = React.useState(false);
    const handleShow = (showValue) => setShow(showValue);

    return (
        <Row>
            <LeftCol md={8}>
                <PersonalDetails parentShowFn={handleShow}/>
                <Form />
            </LeftCol>
            <RightCol md={4}>
                <EmailVerification />
                <FAQs />
            </RightCol>
            <Modal show={show} onHide={()=>handleShow(false)}>
{/* It was getting called again and again and throwing limit error*/}
                <Modal.Header closeButton>
                  <Modal.Title>Modal heading</Modal.Title>
                </Modal.Header>
                <Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
                <Modal.Footer>
                  <Button variant="secondary" onClick={()=>handleShow(false)}>
                    Close
                  </Button>
                  <Button variant="primary" onClick={()=>handleShow(false)}>
                    Save Changes
                  </Button>
                </Modal.Footer>
            </Modal>
        </Row>
    )
}

export default OnboardPage
pl2ern4
  • 340
  • 2
  • 10
1

You have set callback incorrectly for setShow. You call setShow every time it's re-rendered. -> Loop infinity

Should pass a callback like: () => setShow(flase);

Viet Dinh
  • 1,871
  • 1
  • 6
  • 18