reactjsnavbarsimplemodal

Modal component not loading from Navbar link in React


Modal component not loading from Navbar link in React

I have a Navbar component in my React project, and all other links are working successfully except for the contact link.

The contact link should open up a Modal component, which in turn opens the ContactForm component, but I can't get the link to work.

I am declaring a showModal state within the Navbar component which is initially set to false. I have then created an openModal function that is activated once the user clicks on the contact link, and should change the showModal state to true and return the Modal component.

When the Modal component is called, the showModal state is passed as an argument, and if true, this should trigger the rendering of the ContactForm component, but this is not happening.

I will include excerpts of my code below, and I also have replicated my issue on codesandbox here https://codesandbox.io/s/navbar-modal-pcg9w2?file=/src/Modal.js.

I have simplified my code to purely illustrate the issue I have, so you will not see the other links working, but they do, my only issue is the contact link.

App.js

import "bootstrap/dist/css/bootstrap.min.css";
import Navbar from "./Navbar";

export default function App() {
  return (
    <div className="App">
      <Navbar />
    </div>
  );
}

Navbar.js

import Container from "react-bootstrap/Container";
import Nav from "react-bootstrap/Nav";
import Navbar from "react-bootstrap/Navbar";
import Modal from "./Modal";
import { useState } from "react";
import styles from "./Navbar.module.css";
import { scroller } from "react-scroll";
import { FaLinkedin } from "react-icons/fa";

const NavBar = () => {
  const [showModal, setShowModal] = useState(false);

  const openModal = () => {
    setShowModal(true);
    //console log to check it's working
    console.log(showModal);
    //pass showModal as argument to Modal component
    return <Modal showModal={showModal} />;
  };

  return (
    <div>
      <Navbar className={styles.colorNav} variant="dark">
        <Container className={styles.container}>
          <Navbar.Brand
            whileHover={{ scale: 1.1 }}
            onClick={() =>
              scroller.scrollTo("home", {
                smooth: true,
                offset: -10,
                duration: 500
              })
            }
          >
            LOGO
          </Navbar.Brand>
          <Nav className={styles.meAuto}>
            <Nav.Link
              className={styles.navLink}
              onClick={() =>
                scroller.scrollTo("services", {
                  smooth: true,
                  offset: -80,
                  duration: 500
                })
              }
            >
              services
            </Nav.Link>
            <Nav.Link
              className={styles.navLink}
              onClick={() =>
                scroller.scrollTo("about", {
                  smooth: true,
                  offset: -50,
                  duration: 500
                })
              }
            >
              about
            </Nav.Link>
            <Nav.Link
              className={styles.navLink}
              onClick={() =>
                scroller.scrollTo("portfolio", {
                  smooth: true,
                  offset: -50,
                  duration: 100
                })
              }
            >
              portfolio
            </Nav.Link>
            <Nav.Link className={styles.navLink} onClick={openModal}>
              contact
            </Nav.Link>
            <Nav.Link className={styles.navLink}>
              <FaLinkedin />
            </Nav.Link>
          </Nav>
        </Container>
      </Navbar>
    </div>
  );
};

export default NavBar;

Modal.js

import ContactForm from "./ContactForm";

//receives showModal from Navbar component
const Modal = ({ showModal }) => {
  //if showModal true then show ContactForm component
  return <div>{showModal && <ContactForm />}</div>;
};

export default Modal;

ContactForm.js

import React from "react";
import { useForm } from "react-hook-form";
import styles from "./ContactForm.module.css";

const ContactForm = ({ setShowModal }) => {
  const {
    register,
    handleSubmit,
    formState: { errors }
  } = useForm({
    defaultValues: {
      firstName: "",
      lastName: "",
      query: ""
    }
  });
  const onSubmit = (data) => console.log(data);
  console.log(errors);

  return (
    <div className={styles.contactFormContainer}>
      <form className={styles.gridContainer} onSubmit={handleSubmit(onSubmit)}>
        <h2 className={styles.h2}>Contact Form</h2>

        <input
          className={styles.firstName}
          type="text"
          placeholder="First name"
          {...register("firstName", { required: true, maxLength: 80 })}
        />

        <input
          className={styles.lastName}
          type="text"
          placeholder="Last name"
          {...register("lastName", { required: true, maxLength: 100 })}
        />

        <input
          className={styles.email}
          type="text"
          placeholder="email"
          {...register("email", {
            required: true,
            pattern: /^\S+@\S+$/i
          })}
        />

        <input
          className={styles.query}
          type="text"
          placeholder="Please enter your query (max 500 characters):"
          {...register("query", {
            required: true,
            maxLength: 500
          })}
        />

        <input
          className={styles.submit}
          type="submit"
          onClick={() => setShowModal(false)}
        />
      </form>
    </div>
  );
};

export default ContactForm;

I am fairly new to this, so I realise I will have made a stupid rookie error, but I have looked at several previous stackoverflow answers and elsewhere online, and I still can't figure out where I am going wrong. I'd appreciate any help, thanks!


Solution

  • You should change your code in the Navbar.js

    In the onenModal() function you should remove the return statement. It should only change the state of the showModal variable.

    And you should add the Modal component to the end of the return of the Navbar component itself. For example:

            ...
            </Container>
          </Navbar>
          <Modal showModal={showModal} />
        </div>
    

    Now the modal content will be visible whenever you click on your link. But you should change your modal, that it really displays its content in a modal. I assume that you should use some Bootstrap component for it.