skip to Main Content

I have a component that theres a button that when I click in this button a modal needs to be shows up, I created the Modal in another file, so I’m trying to call the function to open this modal.

I have some problems to do it works as I need, so I need your help guys.

When I click in the button the workflow access the function but I have the error below:

react-dom.development.js:16227 Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

  1. You might have mismatching versions of React and the renderer (such as React DOM)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app
    See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
    at Object.throwInvalidHookError (react-dom.development.js:16227:1)
    at useState (react.development.js:1622:1)
    at ModalDialog (ModalDialog.js:8:1)
    at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1)
    at invokeGuardedCallback (react-dom.development.js:4277:1)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:4291:1)
    at executeDispatch (react-dom.development.js:9041:1)
    at processDispatchQueueItemsInOrder (react-dom.development.js:9073:1)
    at processDispatchQueue (react-dom.development.js:9086:1)

This is my ModalDialog.js the File where I have the modal and the function to open and close it):

import React, {useState} from "react";
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' 
import {faTrash } from "@fortawesome/free-solid-svg-icons"; 

function ModalDialog() {
  const [show, setShow] = useState(false);
  const handleClose = () => setShow(false);
  const handleShow = () => setShow(true);

  return (
    <> 
  <Modal
    show={show}
    onHide={handleClose}
    backdrop="static"
    keyboard={false}
  >
    <Modal.Header closeButton>
      <div class="container ">
        <div class="h2 d-flex justify-content-start">Album Name</div>
      </div>  
    </Modal.Header>

    <Modal.Body>
    <div class="container justify-content-center">
      <table class="mt-3 table table-hover table-light text-center">
        <thead>
          <tr>
            <th scope="col">Album Name</th>
            <th scope="col">Release Date</th>   
            <th scope="col"></th>                       
          </tr>
        </thead>

        <tbody>
          <tr id="1">
            <td>Album 1</td>
            <td>2023-06-27</td>  
            <td>
              <FontAwesomeIcon icon={faTrash} />
            </td>                          
          </tr>
        </tbody>
      </table>
    </div>
    </Modal.Body>
    <Modal.Footer>
      <div class="container d-flex justify-content-center">
        <Button variant="primary ms-2" onClick={handleClose}>
          Add New Song
        </Button>                     
      </div>       
    </Modal.Footer>
  </Modal>
</>
  );
}

export default ModalDialog;

This is my AlbumCard.js the file where I have a button that I’d like to click to open the modal present in the file ModalDialog.js

  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
  import {faCompactDisc,faCirclePlus,faSquareArrowUpRight } from "@fortawesome/free-solid-svg-icons";
  import ModalDialog from '../Components/ModalDialog'
  import '../Styles/AlbumCard.css';

  const AlbumCard = () => {
        return (
      <div class="mt-4 container width: 92%">
        <div class="container">
          <div class="row">
            <div class="col">
              <div class="h3 d-flex justify-content-start">
                <FontAwesomeIcon icon={faCompactDisc} />
                <div class="ms-3">
                  Album List
                </div>   
              </div>         
            </div>

        <div class="col">
          <div class="h3 d-flex justify-content-end">
            <div class="">
              <button type="button" class="btn btn-info bg-dark text-light" onClick={ModalDialog}> <---- I'd like to call the function to open the modal here.---->
                Add
                <span class="ms-2">
                <FontAwesomeIcon icon={faCirclePlus} />
                </span>                                       
              </button>
            </div>   
          </div>         
        </div>            
      </div>
    </div>

    <table class="mt-3 table table-hover table-light">
      <thead>
        <tr id="1">
          <th scope="col">Album Name</th>
          <th scope="col">Release Date</th>   
          <th scope="col"></th>                       
        </tr>
      </thead>

      <tbody>
        <tr>
          <td>Album 1</td>
          <td>2023-06-27</td>  
          <td>
            <FontAwesomeIcon icon={faSquareArrowUpRight} />
          </td>                          
        </tr>

        <tr>
          <td>Album 1</td>
          <td>2023-06-27</td>  
          <td>
            <FontAwesomeIcon icon={faSquareArrowUpRight} />
          </td>                          
        </tr> 

        <tr>
          <td>Album 1</td>
          <td>2023-06-27</td>  
          <td>
            <FontAwesomeIcon icon={faSquareArrowUpRight} />
          </td>                          
        </tr> 

        <tr>
          <td>Album 1</td>
          <td>2023-06-27</td>  
          <td>
            <FontAwesomeIcon icon={faSquareArrowUpRight} />
          </td>                          
        </tr> 

        <tr>
          <td>Album 1</td>
          <td>2023-06-27</td>  
          <td>
            <FontAwesomeIcon icon={faSquareArrowUpRight} />
          </td>                          
        </tr> 

        <tr>
          <td>Album 1</td>
          <td>2023-06-27</td>  
          <td>
            <FontAwesomeIcon icon={faSquareArrowUpRight} />
          </td>                          
        </tr> 

        <tr>
          <td>Album 1</td>
          <td>2023-06-27</td>  
          <td>
            <FontAwesomeIcon icon={faSquareArrowUpRight} />
          </td>                          
        </tr> 

        <tr>
          <td>Album 1</td>
          <td>2023-06-27</td>  
          <td>
            <FontAwesomeIcon icon={faSquareArrowUpRight} />
          </td>                          
        </tr> 

        <tr>
          <td>Album 1</td>
          <td>2023-06-27</td>  
          <td>
            <FontAwesomeIcon icon={faSquareArrowUpRight} />
        </td>                          
        </tr> 
      </tbody>
    </table>   
  </div> 
    );
  };

  export default AlbumCard;

Thank you in advance !

3

Answers


  1. Chosen as BEST ANSWER

    Guys I uploaded two picures to show what's happening when I start to debug the code:

    When I click in this button [Add +] I call the function in another file, but when I go ahed to the next line of my function, the error shows:

    After click in the button Add +

    After run the function


  2. This is not the correct way of writing the code.you are calling a react component function in your click handler.You need to write the Modal in your jsx like other component(add it anywhere for now but I would recommend to use react portal for modal) and use the useState to hide/show.send show and onHide to your modal dialog component and accept that as props.it is used by react bootstrap modal component.

     const [modalShow, setModalShow] = useState(false);
     <ModalDialog show={modalShow} onHide={()=>setModalShow(false)}/>
    

    Add below code to your button

    onClick={()=>{setModalShow(true)}}
    
    Login or Signup to reply.
  3. The issue you’re facing is related to calling a function component directly as an event handler. In your AlbumCard.js file, you’re trying to call the ModalDialog function component directly on the button’s onClick event, which is causing the "Invalid hook call" error.

    To fix this, you need to modify your code as follows:

    import { useState } from 'react';
    import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
    import { faCompactDisc, faCirclePlus, faSquareArrowUpRight } from '@fortawesome/free-solid-svg-icons';
    import ModalDialog from '../Components/ModalDialog';
    import '../Styles/AlbumCard.css';
    
    const AlbumCard = () => {
      const [showModal, setShowModal] = useState(false);
    
      const openModal = () => {
        setShowModal(true);
      };
    
      const closeModal = () => {
        setShowModal(false);
      };
    
      return (
        <div className="mt-4 container width: 92%">
          <div className="container">
            <div className="row">
              <div className="col">
                <div className="h3 d-flex justify-content-start">
                  <FontAwesomeIcon icon={faCompactDisc} />
                  <div className="ms-3">Album List</div>
                </div>
              </div>
    
              <div className="col">
                <div className="h3 d-flex justify-content-end">
                  <div>
                    <button type="button" className="btn btn-info bg-dark text-light" onClick={openModal}>
                      Add
                      <span className="ms-2">
                        <FontAwesomeIcon icon={faCirclePlus} />
                      </span>
                    </button>
                  </div>
                </div>
              </div>
            </div>
          </div>
    
          {/* Rest of your code */}
    
          {/* Render the ModalDialog component conditionally */}
          {showModal && <ModalDialog handleClose={closeModal} />}
        </div>
      );
    };
    
    export default AlbumCard;
    

    In the updated code, I’ve made the following changes:

    1. Added a new state variable showModal using the useState hook to keep track of whether the modal should be shown or not.

    2. Created two functions openModal and closeModal to handle the opening and closing of the modal by updating the showModal state.

    3. Modified the button’s onClick event to call the openModal function.

    4. Rendered the ModalDialog component conditionally based on the showModal state.

    Note that you need to pass the closeModal function as a prop to the ModalDialog component so that it can be used to close the modal when needed.

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