React. Show Bootstrap modal in different component - reactjs

I am trying to display a Bootstrap modal which is in a different component than the button which open the modal.
Header.js
import React, { useState } from "react";
import Search from "./Search";
function Header() {
const [showModal, setShowModal] = useState(false);
const handleShowModal = () => setShowModal(true);
return (
<header>
<ul>
<li>
<button className="btn" onClick={handleShowModal}>
Search
</button>
</li>
</ul>
<Search shoWChildModal={handleShowModal} />
</header>
);
}
export default Header;
Search.js
import React, { useState } from "react";
import Modal from 'react-bootstrap/Modal';
function Search(shoWChildModal) {
const [showModal, setShowModal] = useState(false);
const handleCloseModal = () => setShowModal(false);
return (
<Modal show={shoWChildModal} onHide={handleCloseModal}>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
<Modal.Footer>
<button variant="secondary" onClick={handleCloseModal}>
Close
</button>
<button variant="primary" onClick={handleCloseModal}>
Save Changes
</button>
</Modal.Footer>
</Modal>
);
}
export default Search;
Actually the modal opens on page load. Would it be possible to open the modal with the onclick event of the button?

Related

ReactJS Modal Window onClick

My ReactJS Modal Window do not work.
Here is code:
import React from 'react';
import './Modal.css';
import Button from 'react-bootstrap/Button';
const Modal = ({ handleClose, show, children }) => {
const showHideClassName = show ? "modal display-block" : "modal display-none";
return (
<div className={showHideClassName}>
<section className="card modal-main">
{children}
<div className="clear"></div>
<Button onClick={handleClose}>
Close
</Button>
</section>
</div>
);
};
export default Modal;
And here is code in my component:
function modalState(state) {
return state;
};
<Modal show={modalState(setModal)} handleClose={modalState(false)}>
{
<div></div>
}
</Modal>
And if I click Add user button then nothing happens:
<Button variant="primary" size="sm" onClick={() => {
setModal = true;
modalState(setModal);
}}>Add User</Button>{' '}
What should I doing wrong?
Try to use useState hook.
Your Modal component.
import { useState } from 'react';
import './Modal.css';
import Button from 'react-bootstrap/Button';
const Modal = ({ show, children }) => {
const [modalState, setModalState] = useState(show);
const showHideClassName = show ? "modal display-block" : "modal display-none";
return (
<div className={showHideClassName}>
<section className="card modal-main">
{children}
<div className="clear"></div>
<Button onClick={() => setModalState(false)}>
Close
</Button>
</section>
</div>
);
};
export default Modal;
And your component where calls Modal component.
import { useState } from 'react';
import Modal from './path/Modal';
const CustomComponent = () => {
const [modalState, setModalState] = useState(false);
return (
<>
<Modal show={modalState}>
{
<div></div>
}
</Modal>
<Button
variant="primary" size="sm"
onClick={() => setModalState(true)}
>
Add User
</Button>
</>
);
}
export default CustomComponent;
But please note that this would be just a temporary solution based on your current codes. If you want a better and permanent solution, I'd like to recommend to implement the global state management thru your whole codebase using Redux or Recoil.
In the onclick event useState set is not done to set the value of the Modal
setModal({modal:true})
And
<Modal show={modal} handleClose={modalState(false)}>
{
<div></div>
}
</Modal>
I think if you do this it will work.
const [isVisibleModal, setVisibleModal] = useState(false); // <- add
function closeModal() {
setVisibleModal(!isVisibleModal);
};
<Modal show={isVisibleModal} handleClose={closeModal}>
{
<div></div>
}
</Modal>
<Button
variant="primary"
size="sm"
onClick={() => setVisibleModal(true)}
>
Add User
</Button>
Hope this helps you!
You should use setVisibleModal function same page like this code
import React, { useState } from 'react';
const YourComponent = () => {
const [isVisibleModal, setVisibleModal] = useState(false); // <- add
function closeModal() {
setVisibleModal(!isVisibleModal);
};
return (
<>
<Modal show={isVisibleModal} handleClose={closeModal}>
{
<div></div>
}
</Modal>
<Button
variant="primary"
size="sm"
onClick={() => setVisibleModal(true)}
>
Add User
</Button>
</>
)
}
export default YourComponent;

reactJS - Invalid hook call. Hooks can only be called inside of the body of a function component

I am fairly new to reactJS and I am trying to use bootstrap Modal like so:
class Footer extends Component {
render() {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<footer className="footer-bottom">
<Container>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="primary" onClick={handleClose}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</Container>
</footer>
);
}
}
However I am getting this error:
Invalid hook call. Hooks can only be called inside of the body of a function component.
My question is how do I turn my const (show, setShow, handleClose, handelShow) into a function to get this to work?
Hooks can only be used in function components, so your component cannot extend React.Component. Instead of this:
class Footer extends Component {
do this:
Footer = (props) => {
//rest of the code
}
Because you are now not extending the Component class, you don't need a render() function. Just do a return from the Footer function instead.
The problem is that the component you're making right now is a class component, not a function component. As of now, hooks don't work inside classes. Try changing your code to this:
export default function Footer() {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<footer className="footer-bottom">
<Container>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="primary" onClick={handleClose}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</Container>
</footer>
);
}
Hooks cant be used in class components, you can convert it to a functional component:
const Footer = () => {
return (
...
)
}
you can also leave it as class component:
class Footer extends Component {
constructor(props){
super(props)
this.state = {
show: false
}
}
}
Here's how you should create your function:
//add your imports
import { useState } from 'react';
//pass props if you're using prop drilling
function Footer(props) {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<footer className="footer-bottom">
<Container>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="primary" onClick={handleClose}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</Container>
</footer>
);
}
//export the function
export default Footer;

ReactJS Modal with Material UI

I'm trying to make a reusable confirmation modal with Material UI but when I press CANCEL or OK the modal does not close.
The code is here:
https://codesandbox.io/s/lucid-hoover-sput6?file=/src/App.js
I can't figure it out why the pop don't dissapear.
LE: added the code here so it remains
ConfirmModal.js
import React from "react";
import { Button } from "#material-ui/core";
import Dialog from "#material-ui/core/Dialog";
import DialogActions from "#material-ui/core/DialogActions";
import DialogContent from "#material-ui/core/DialogContent";
import DialogContentText from "#material-ui/core/DialogContentText";
const ConfirmModal = (props) => {
const { content, open, setOpen, onConfirm } = props;
return (
<Dialog
open={open}
onClose={() => setOpen(false)}
aria-labelledby="dialog-title"
>
<DialogContent>
<DialogContentText>{content}</DialogContentText>
</DialogContent>
<DialogActions>
<Button autoFocus onClick={() => setOpen(false)} color="primary">
Cancel
</Button>
<Button
onClick={() => {
setOpen(false);
onConfirm();
}}
color="primary"
>
OK
</Button>
</DialogActions>
</Dialog>
// </div>
);
};
export default ConfirmModal;
App.js
import React, { useState } from "react";
import { IconButton } from "#material-ui/core";
import { Input as InputIcon } from "#material-ui/icons";
import ConfirmModal from "./ConfirmModal";
export default function App() {
const [confirmOpen, setConfirmOpen] = useState(false);
const handleLogout = () => {
console.log("this hould logout the user");
};
return (
<div className="App">
<h2>Press the button below so the confirmation modal appears </h2>
<IconButton color="inherit" onClick={() => setConfirmOpen(true)}>
<InputIcon />
<ConfirmModal
content="Are you sure you want to leeeave us ?"
open={confirmOpen}
setOpen={setConfirmOpen}
onConfirm={handleLogout}
/>
</IconButton>
</div>
);
}
Move the modal out of the button. The Modal's cancel/confirm/backdrop click events are propagating (bubbling) up to the open button (IconButton) and its onClick handler is just reopening the modal by setting confirmOpen state true.
export default function App() {
const [confirmOpen, setConfirmOpen] = useState(false);
const handleLogout = () => {
console.log("this hould logout the user");
};
return (
<div className="App">
<h2>Press the button below so the confirmation modal appears </h2>
<IconButton color="inherit" onClick={() => setConfirmOpen(true)}>
<InputIcon />
</IconButton>
<ConfirmModal
content="Are you sure you want to leeeave us ?"
open={confirmOpen}
setOpen={setConfirmOpen}
onConfirm={handleLogout}
/>
</div>
);
}

Opening a Modal in React with an ID passed to the component

I have an application which prompts a user to add an entry via a modal. However, I can't figure out how to call the modal from the function and neither can I figure out how to pass the id to the modal.
So far I've been able to get the two parts written up and compiled but not working together
'Add Entry' button
import React from 'react';
import '../../App.css'
import VideoModal from '../components/VideoModal'
function NewEntry ({event}){
return (
<span><i class="fa fa-plus-circle" aria-hidden="true"></i></span>
<VideoModal entry={event}
);
}
export default NewEntry;
Note that this doesn't call the modal component. I've attempted variations of onClick={this.closeModal} for the <I> tag to no avail, but this obviously won't work. And I've included the modal as a component.
I know, I know this isn't the right way of doing this, I just haven't yet found examples I can wrap my head around.
The Modal
import React, { Component } from "react";
import { Modal, Button } from "react-bootstrap";
import '../../App.css'
class VideoModal extends Component {
state = {
isOpen: false
};
openModal = () => this.setState({ isOpen: true });
closeModal = () => this.setState({ isOpen: false });
render() {
return (
<>
<Modal show={this.state.isOpen} onHide={this.closeModal}>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={this.closeModal}>
Close
</Button>
</Modal.Footer>
</Modal>
</>
);
}
}
export default VideoModal;
First of all, the VideoModal tag is not closed, pay attention to it.
Then you can move the open/close logic outside the modal, inside NewEntry:
import React, { Component } from 'react';
import '../../App.css'
import VideoModal from '../components/VideoModal'
class NewEntry extends Component {
state = {
isModalOpen: false
};
openModal = () => this.setState({ isModalOpen: true });
closeModal = () => this.setState({ isModalOpen: false });
render() {
return (
<span onClick={() => this.openModal()}><i class="fa fa-plus-circle" aria-hidden="true"></i></span>
<VideoModal closeModal={() => this.closeModal()} isOpen={this.state.isOpen} />
);
}
}
export default NewEntry;
And use VideoModal as a pure component:
import React from "react";
import { Modal, Button } from "react-bootstrap";
import '../../App.css'
function VideoModal (props) {
const { isOpen, closeModal } = props;
return (
<>
<Modal show={isOpen} onHide={closeModal}>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={closeModal}>
Close
</Button>
</Modal.Footer>
</Modal>
</>
);
}
export default VideoModal;

How to use the react-bootstrap modal

I have a component called Navbar. When I click on the take note button in the Navbar component I want it to show a modal using react-bootstrap. How can I go about it. Here is my code
class Navbar extends Component {
render(){
return (
<React.Fragment>
<nav style={navStyle}
className="navbar navbar-expand-md">
<p style={noteStyle}>Notes</p>
<button
style={btnStyle}
className="btn btn-light">
Take Note
</button>
</nav>
</React.Fragment>
)
}
};
Here is a quick demo. Hope it helps.
import React, { useState } from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import "./styles.css";
import { Button, Modal } from "react-bootstrap";
const styles = {
navStyle: { background: "red" },
noteStyle: { color: "yellow" },
btnStyle: { background: "blue" }
};
const App = () => {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<>
<nav style={styles.navStyle} className="navbar navbar-expand-md">
<p style={styles.noteStyle}>Notes</p>
<Button style={styles.btnStyle} variant="primary" onClick={handleShow}>
Take Note
</Button>
</nav>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="primary" onClick={handleClose}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</>
);
};
Basically you need to trigger modal whenever you want to click on the navbar. You can easily find a reference on the react-bootstrap component library. How to show and hide modal(i.e using state flags). I added code for reference. I would suggest doing your own tweaks to learn faster.
import React, { useState } from "react";
import ReactDOM from "react-dom";
import {
Navbar,
NavbarBrand,
Nav,
Button,
Modal,
ModalHeader,
ModalBody,
ModalFooter
} from "reactstrap";
import "./styles.css";
function App() {
const [modal, setModal] = useState(false);
const toggle = () => setModal(!modal); //Set hide or show modal
return (
<div className="App">
<Navbar color="light" light expand="md">
<NavbarBrand href="/">reactstrap</NavbarBrand>
<Nav className="ml-auto" navbar>
<Button onClick={toggle}>Take Note</Button> // Show modal
</Nav>
</Navbar>
//Modal
<Modal isOpen={modal} toggle={toggle}>
<ModalHeader toggle={toggle}>Create Note</ModalHeader>
<ModalBody>Your Note</ModalBody>
<ModalFooter>
<Button color="primary" onClick={toggle}>
Do Something More
</Button>{" "}
<Button color="secondary" onClick={toggle}>
Cancel
</Button>
</ModalFooter>
</Modal>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Live demo : https://codesandbox.io/s/pensive-leaf-vkrqf

Resources