'show and hide contact form react
I have a <ContactUs /> component which has my contact us form. i want to show and hide that component when get in touch button in the <navbar /> component is clicked.
I tried setState for showContact (in
<contactUs />) it works in contactUs but i cant change the state from<navbar />.
contactUs.js
const [showContact, setShowContact] = useState(false);
return <div className={`contact-us-container ${showContact ? "shown" : ""}`}>
// form
</div>
Navbar.js
<a href="#" className="navbar-item cta-button" onClick={??}>Get in touch</a> //should change showContact
App.js
<navbar />
<home /> // homepage content
<contactUs />
Solution 1:[1]
You can simply update your existing code like this and pass the props from App.js to other files
contactUs.js
import { Fragment } from "react";
export default function ContactUS({ showContact }){
return (
<Fragment>
{ showContact ? (
<div className="contact-us-container">
// form
</div>
):("") }
</Fragment>
);
}
navbar.js
import { Fragment } from "react";
export default function NavBar({ setShowContact }){
return (
<Fragment>
<a href="#" className="navbar-item cta-button" onClick={ () => setShowContact(true) }>Get in touch</a>
</Fragment>
);
}
app.js
import Home from "path/to/Home ";
import NavBar from "path/to/Navbar";
import ContactUS from "path/to/ContactUS ";
import { Fragment, useState } from "react";
export default function App(){
const [showContact, setShowContact] = useState(false);
return (
<Fragment>
<NavBar setShowContact={setShowContact} />
<Home />
<ContactUS showContact={showContact} />
</Fragment>
);
}
Solution 2:[2]
contactUs.js
export default function ContactUs() {
return <div>Contact us form here</div>
}
navbar.js
export default function Navbar(props) {
return (
<nav>
...
{props && props.showContactForm
? <button onClick={() => props.setShowContactForm(false)}>Hide contact us</button>
: <button onClick={() => props.setShowContactForm(true)}>Show contact us</button>
}
</nav>
)
}
home.js
export default function Home() {
const [showContactForm, setShowContactForm] = useState(false)
return (
<div>
...
<Navbar showContactForm={showContactForm} setShowContactForm={setShowContactForm} />
{showContactForm && <ContactUs />
</div>
)
}
Solution 3:[3]
Wrap Navbar and contact us form inside home component and lift up state and pass showContact from parent
in Home component
const [showContact , setshowContact] = useState(false);
<navbar setShowContact = {setShowContact}/>
<contactUs showContact={showContact} />
in Navbar component
const {setShowContact} = props
<a href="#" className="navbar-item cta-button" onClick={() => setshowContact(false)}>Get in touch</a> //should change showContact
Solution 4:[4]
I would advise to use react router, in order to navigate to the component. So whenever you click on Get in touch button, you navigate to the ContactUs component, with something like this (instead of the a that you have):
<Link to="/contactUs">Get in touch</Link>
You will also need some route definition at the root of your App, to handle the rooting
Solution 5:[5]
For rendering, you can render it like this in the render function - {showContact && <ContactUs />} or the condition that you already mentioned in your answer
i.e- return <div className={`contact-us-container ${showContact ? "shown" : ""}`}> // form </div>
To change it's state from navbar, you can have to pass the setShowContact function as a prop to <navbar /> component like shown below.
`` ```
Now inside the navbar component you can use props.setShowContact(true/false) to show or hide the contact form.
Solution 6:[6]
A modal might be useful in this case. For those we use a React portal. It positions the modal outside of the DOM hierarchy of the parent element. You can add in all the HTML you want. They're really useful for forms.
A typical use case for portals is when a parent component has an overflow: hidden or z-index style, but you need the child to visually “break out” of its container. For example, dialogs, hovercards, and tooltips.
(Also pop-ups and modals.)
The parent component should manage the state of the modal (open or closed), so we need to pass down a handler to both the Nav and ContactUs components.
const { useState } = React;
// Create the modal component which accepts two handlers,
// and "children" which is the HTML you want to show
function Modal({ isOpen, onClose, children }) {
if (!isOpen) return null;
return ReactDOM.createPortal(
<div className="modal">
{children}
<button
className="closemodal"
onClick={onClose}
>Close
</button>
</div>,
document.body
);
}
// Pass in the handler to the Nav component
function Nav({ handleModal }) {
return (
<nav>
<a onClick={handleModal}>Get in touch</a>
</nav>
);
}
// ContactUs builds the form within the modal
// We pass in the showModal state, and the handler
function ContactUs({ showModal, handleModal }) {
return (
<Modal isOpen={showModal} onClose={handleModal}>
<h3>Contact Us</h3>
<fieldset>
<legend>Email</legend>
<input type="email" />
<button
className="send"
type="button"
>Send</button>
</fieldset>
</Modal>
);
}
function Example() {
const [ showModal, setShowModal ] = useState(false);
// Our main handler for the modal. It simply
// toggles between true and false
function handleModal() {
setShowModal(!showModal);
}
return (
<div>
<Nav handleModal={handleModal} />
<ContactUs
showModal={showModal}
handleModal={handleModal}
/>
</div>
);
};
ReactDOM.render(
<Example />,
document.getElementById('react')
);
nav { padding: 1em; margin: 0.2em; background-color: #efefef; }
nav a { border: 2px solid #454545; padding: 0.25em; }
nav a:hover { cursor: pointer; background-color: #dfdfdf; }
.modal { position: fixed; inset: 0; background-color: white; margin: 0.5em; border: 2px solid #343434; display: flex; flex-direction: column; align-items: center; justify-content: center; overflow: hidden; overflow-y:scroll; transition: all 0.3s ease-in-out; z-index: 999; }
fieldset { margin-bottom: 1em; background-color: #efefef; }
.closemodal { padding: 0.5em; background-color: #336699; color: white; }
.send { background-color: #44aa77; color: white; }
.closemodal:hover, .send:hover { cursor: pointer; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | udoyhasan |
| Solution 2 | Coupz |
| Solution 3 | |
| Solution 4 | TheTisiboth |
| Solution 5 | Ankit Saxena |
| Solution 6 |
