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 />
CodePudding user response:
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>
);
}
CodePudding user response:
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>
)
}
CodePudding user response:
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
CodePudding user response:
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
CodePudding user response:
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.
CodePudding user response:
A modal might be useful in this case. For those we use React portals. 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.
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 Modal
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 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: 1em; }
nav a { border: 2px solid #454545; padding: 0.5em; }
nav a:hover { cursor: pointer; background-color: #efefef; }
.modal { position: fixed; inset: 0; background-color: rgba(0, 0, 0, 0.1); margin: 1em; border: 2px solid #343434; display: flex; flex-direction: column; align-items: center; justify-content: center; transition: all 0.3s ease-in-out; overflow: hidden; z-index: 999; }
fieldset { margin-bottom: 1em; }
.closemodal { padding: 0.5em; background-color: #44aa77; color: white; }
.closemodal: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>