React + Bootstrap modal questions - reactjs

I am trying to put a modal dialog using react-bootstrap and having issues.
I have a "HintComponent" which consists of a bunch of buttons
<div className="col-5 d-grid gap-2 borderGeneral">
<button className="buttonGeneral" >Label here</button>
<button className="buttonGeneral">SUMMARY</button>
</div>
and I want to launch a Modal dialog on clicking a button.
Looking at the react-bootstrap site, I have the following (taken straight from the site)
import React, {useState} from 'react';
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';
import render from 'react-dom';
function Example() {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<>
<Button variant="primary" onClick={handleShow}>
Launch demo modal
</Button>
<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>
</>
);
}
render(<Example />);
My issue is - how do I call the Modal from the HintComponent? If I try to import the Modal (in this case ) and call it as just I get a warning about module having no exports.
Can anyone give me a hint?

Hi very simple you need to use this component in your HintComponent and pass a prop showModal={true} but before this, you need to receive that prop in your modal component and set it in state using React.useEffect
So your final code will be like below:
ModalComponent
import React, {useState} from 'react';
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';
import render from 'react-dom';
function Example(props) {
const {showModal = false, onClose = ()=>{}} = props;
const [show, setShow] = useState(showModal);
React.useEffect(()=>{
setShow(showModal);
},[showModal]);
const handleClose = () => {
setShow(false);
// just to have custom function for modal close which will be used can be used in HintComponent maybe you want to perform somehting else after modal close.
typeof onClose === 'function' && onClose();
};
const handleShow = () => setShow(true);
return (
<>
<Button variant="primary" onClick={handleShow}>
Launch demo modal
</Button>
<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>
</>
);
}
render(<Example />);
I would recommend do not manage Modal visibility in its component but control it from the parent component in your case HintComponent.

Related

Looking for suggestions for a better solution

So I have a site which has 12 buttons. 6 of these buttons will need to launch a popup with a different video and 6 buttons will need to launch a popup with 6 images.
Now, currently, I am experimenting with a single popup displaying an image. And this is fairly easy, I set a state
const [showModal, setShowModal] = useState(false);
And then I have a button which will set the show onClick and then a model is shown - eg
<button className="buttonGeneral" onClick={()=>setShowModal(true)}>SUMMARY11</button> <ModalReact showModal={showModal} onClose={() => setShowModal(false)} image={props.image_1} size='med'/>
Thinking about this, I am thinking I will need 2 different types of modals, one for video and one for images. But with the approach above, I am going to need to useState with 12 different states. This seems a bit wrong, but I cannot think of any other way.
For completeness, here is the ModalReact component
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';
import '../styles/react-bs.css';
function ModalReact({showModal = false, onClose = () =>{}, image, size}) {
console.log("im ", image)
return (
<Modal
size={size}
show={showModal}
onHide={onClose}
backdrop="static"
keyboard={false}
// dialogClassName="videoPopup"
>
<Modal.Body><img src={image} alt="lala"></img></Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={onClose}>
Close
</Button>
</Modal.Footer>
</Modal>
)
}
export default ModalReact
You need to maintain different states for all the buttons. I would suggest writing a custom component with its state maintained in the same component so that it's available for only that component. Based on that, we can open a modal from its state variable.
export default function ModalReact({ itemNum }) {
const [showModal, setShowModal] = useState(false);
const handleClose = () => setShowModal(false);
const handleShow = () => setShowModal(true);
return (
<>
<Button variant="primary" onClick={handleShow}>
Launch demo modal {itemNum}
</Button>
<div style={{ display: "block", width: 700, padding: 30 }}>
<Modal show={showModal} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Modal heading {itemNum}</Modal.Title>
</Modal.Header>
<Modal.Body>
Woohoo, you're reading this text in a modal! {itemNum}
{itemNum > 6 ? "image" : "video"}
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="primary" onClick={handleClose}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</div>
</>
);
}
We can use that from any component. You said you have 12 buttons so iterate and display all those buttons. I have used a simple array and iterating to display all the buttons.
return (
<div className="container">
{Array.from({ length: 12 }, (_, i) => i + 1).map((item) => (
<CustomModal itemNum={item} />
))}
</div>
);
Attached is a sandbox for reference.

react bootstrap hook function insert to react export class

Any idea for modal component without using hooks, and use it inside another, class-based component?
function Example() {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<>
<Button variant="primary" onClick={handleShow}>
Launch demo modal
</Button>
<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>
</>
);
}
render(<Example />);
// example.js
function Example() {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<>
<Button variant="primary" onClick={handleShow}> Launch demo modal </Button>
<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>
</>
);
}
export default Example;
// other-component.js
import Example from './example.js'
function OtherComponent() {
return (
<>
<Example />
</>
);
}

Unable to attach Event Listener to react-bootstrap modal for mouse events using ref

Unable to attach Event Listener to react-bootstrap modal for mouse events using ref
Getting TypeError: Modal.addEventListener is not a function while trying to attach event listener
Error message:
Below is sample code:
import React, { useRef,useState,useEffect } from "react";
import {Button,Modal} from 'react-bootstrap';
function ExampleModal() {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
const cardRef = useRef(null);
useEffect(()=>{
const Modal = cardRef?.current;
// ****TypeError: Modal.addEventListener is not a function*****
Modal?.addEventListener("mousedown",mousedownhandler );
return () => {
// unsubscribe event
Modal?.removeEventListener("mousedown", mousedownhandler);
}}
,[])
const mousedownhandler=()=>{console.log('mousedown on modal')}
return (
<>
<Button variant="primary" onClick={handleShow}>
Launch demo modal
</Button>
<Modal ref={cardRef} 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>
</>
);
}
export default ExampleModal;

How to close Modal in Reactjs?

On button click i was trying to open a model (and modal opening too) and in a same modal it contain a button and on button click i was trying to open another model (and second modal opening too), but when second modal is opening i want first model to be closed. can it be possible?
Here is my sandbox demo https://codesandbox.io/embed/dreamy-herschel-cyetn?fontsize=14&hidenavigation=1&theme=dark
const Practice = () => {
const [modalShow, setModalShow] = useState(false);
const handleSubmit = event => {
setModalShow(true);
};
return (
<div>
<Button onSubmit={handleSubmit} type="submit">
Submit
</Button>
<Modals show={modalShow} onhide={() => setModalShow(false)} />
</div>
);
};
here is my modal part
const Modals = ({ show, onhide }) => {
const [modalShowsec, setModalShowsec] = useState(false);
const Validation = () => {
setModalShowsec(true);
};
return (
<div>
<Modal show={show} onHide={onhide} size="sm" aria-labelledby="contained-modal-title-vcenter" centered>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">HELLO</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>Hi</p>
</Modal.Body>
</Modal>
<button onClick={Validation}> Validate </button>
<Modal show={modalShowsec} onHide={() => setModalShowsec(false)}>
<Modal.Header closeButton />
<Modal.Body>
<p>Hi cool</p>
</Modal.Body>
</Modal>
</div>
);
};
Call onhide inside Validation function. This will hide the first modal.
const Validation = () => {
setModalShowsec(true)
onhide()
}

Unable to use bootstrap-react modal in stateless function

What I want to do is add bootstrap-react modal and fire it from a stateless function. All the examples I can find requires changing the "show" in the state of component, but since Im not using af component I don't really have an idea how to do it.
https://react-bootstrap.github.io/components/modal/
https://react-bootstrap.github.io/components/modal/
You need state somewhere to show the modal. You can use hooks to do it in functional (not really "stateless") component using useState.
function App() {
const [open, setOpen] = useState(false);
return (
<>
<Button variant="primary" onClick={() => setOpen(true)}>
Launch demo modal
</Button>
<Modal show={open} onHide={() => setOpen(false)}>
<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={() => setOpen(false)}>
Close
</Button>
<Button variant="primary" onClick={() => setOpen(false)}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</>
);
}
codesandbox: https://codesandbox.io/embed/z2ky5l128l
If you don't want to do it then you need to pass prop from component that is higher in tree, like:
class App extends React.Component {
state = {
open: true,
}
render() {
return <ModalComponent open={open} hide={() => this.setState({open: false})} />
}
}
function ModalComponent = ({open, hide}) => (
<Modal show={open} onHide={hide}>
<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={hide}>
Close
</Button>
</Modal.Footer>
</Modal>
)
just pass visible state from parrent like below
class parent extends Component {
state = {
modalVisibility : false
}
handleModalVisibility = (action)=> this.setState({modalVisibility : action})
return (
<div>
<button onClick={this.handleModalVisibility.bind(this,true)} >Show Modal</button>
//use this props to show or cancel the modal
<ModalComponent visibility ={this.state.modalVisibility} handleModal={this.handleModalVisibility} />
</div>
)
}
I guess you can do that with useState
https://reactjs.org/docs/hooks-state.html

Resources