Search code examples
reactjsreact-hooksreact-modal

How to update the state declared in parent component to a child component using react hook


My react project contains two components: one is parent and another is child. My parent component looks like this:

import React, {useState } from 'react';
import AddNewModal from './AddNewModal';

const MouseContainer = (props) =>{
const [show,setShow] = useState(false);
const toggle = () => setShow(!show);
return (
    <div>
        <button onClick={()=>setShow(!show)}>Toggle</button>
        <p>{show && <AddNewModal show={props.show} setShow={props.setShow}/>}</p>
    </div>
     )
}export default MouseContainer;

And a child component that renders the modal like this:

import React, {useState} from 'react';
import { Modal, Button } from 'react-bootstrap';
import AddNewForm from './AddNewForm';

const AddNewModal = (show,setShow) => {
return(
    <div>
    <Modal show={show} setShow={setShow}> 
    <Modal.Header>
      <Modal.Title>Modal heading</Modal.Title>
    </Modal.Header>
    <Modal.Body><AddNewForm/></Modal.Body>
    <Modal.Footer>
      <Button variant="secondary" onClick={(props)=>props.setShow(!show)}>
        Cancel
      </Button>
    </Modal.Footer>
  </Modal>
    </div>
  )
}export default AddNewModal;

How can I update the stat so that the "cancel" button close the modal when clicked?


Solution

  • If I understand correctly, you're controlling the modal with the useState hook. If that is so, your problem is regarding which props you are passing to the AddNewModal component.

    You're creating the hook correctly with:

    const [show, setShow] = useState(false);
    

    However, you're passing the wrong props to the AddNewModal component. You're passing a setShow and a show coming from props in the MouseContainer component, here:

    <p>{show && <AddNewModal show={props.show} setShow={props.setShow} />}</p>
    

    However, to use the hook you should pass the variables you declared:

    <p>{show && <AddNewModal show={show} setShow={setShow} />}</p>
    

    I'm not familiar with the bootstrap framework, but I think the prop show of the modal component is controlling whether the modal is being shown or not. If that's the case, you can remove the conditional render as well, resulting in:

    <AddNewModal show={show} setShow={setShow} />
    

    Here's your updated code for the MouseContainer component:

    import React, { useState } from 'react';
    import AddNewModal from './AddNewModal';
    
    const MouseContainer = (props) => {
      const [show,setShow] = useState(false);
      const toggle = () => setShow(!show);
    
      return (
        <div>
            <button onClick={()=>setShow(!show)}>Toggle</button>
            <AddNewModal show={show} setShow={setShow} />
        </div>
      )
    }
    

    Also, you have a small type on the AddNewModal:

    To immediately get the props fields you want on the Functional Component declaration, one must use object destructuring [1], to do that one use curly braces:

    const AddNewModal = ({ show, setShow }) => {

    Doing so, you're not declaring the props object like you're doing in the MouseContainer component. So you can't use it within the function.

    Here's you updated AddNewModal:

    import React, {useState} from 'react';
    import { Modal, Button } from 'react-bootstrap';
    import AddNewForm from './AddNewForm';
    
    const AddNewModal = ({ show, setShow }) => {
      return (
        <div>
          <Modal show={show} setShow={setShow}> 
            <Modal.Header>
              <Modal.Title>Modal heading</Modal.Title>
            </Modal.Header>
            <Modal.Body><AddNewForm/></Modal.Body>
            <Modal.Footer>
              <Button variant="secondary" onClick={() => setShow(!show)}>
                Cancel
              </Button>
            </Modal.Footer>
          </Modal>
        </div>
      )
    }
    

    Sources:

    [1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment