I have a Reactstrap Modal in my react app.
I would like the Modal to be unmounted as long as it is not used.
The way the Modal works in the docs example, it simply hides, but the Modal is still mounted.
How do I cause the Modal to unmount when the user closes it?
import React from 'react';
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
class ModalExample extends React.Component {
constructor(props) {
super(props);
this.state = {
modal: false
};
this.toggle = this.toggle.bind(this);
}
toggle() {
this.setState({
modal: !this.state.modal
});
}
render() {
return (
<div>
<Button color="danger" onClick={this.toggle}>{this.props.buttonLabel}</Button>
<Modal isOpen={this.state.modal} toggle={this.toggle} className={this.props.className}>
<ModalHeader toggle={this.toggle}>Modal title</ModalHeader>
<ModalBody>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={this.toggle}>Do Something</Button>{' '}
<Button color="secondary" onClick={this.toggle}>Cancel</Button>
</ModalFooter>
</Modal>
</div>
);
}
}
export default ModalExample;
Inside your render(), optionally render modal based on this.state.modal value.
render() {
return (
<div>
<Button color="danger" onClick={this.toggle}>{this.props.buttonLabel}</Button>
{ this.state.modal && <Modal isOpen={this.state.modal} toggle={this.toggle} className={this.props.className}>
<ModalHeader toggle={this.toggle}>Modal title</ModalHeader>
<ModalBody>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={this.toggle}>Do Something</Button>{' '}
<Button color="secondary" onClick={this.toggle}>Cancel</Button>
</ModalFooter>
</Modal> }
</div>
);
}
}
Related
How to make PrimeReact FieldSet controllable from an other (parent) component on React?
I have a boolean object toggled, i would like to pass it into child component.
When toggled = true, the FieldSet should be opened.
When toggled = false, the FieldSet should be closed.
import React from "react";
import { Fieldset } from "primereact/fieldset";
const FieldsetDemo = () => {
return (
<div>
<div className="card">
<h5>Toggleable</h5>
<Fieldset legend="Header" toggleable>
<p>
Lorem ipsum dolor sit amet.
</p>
</Fieldset>
</div>
</div>
);
};
Its easy. Working code sandbox: https://codesandbox.io/s/quizzical-snow-so91tv?file=/src/demo/FieldsetDemo.js
const FieldsetDemo = (props) => {
return (
<div>
<div className="card">
<h5>Toggleable</h5>
<Fieldset legend="Header" toggleable collapsed={props.collapsed}>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum.
</p>
</Fieldset>
</div>
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<FieldsetDemo collapsed={true} />, rootElement);
i am not able to update modal state based on received props value from other component in reactjs. i have tried all things but not working. please suggest on it it will be appreciable.
const ModalExample = ({ elem }) => {
const [modal, setModal] = useState(elem);
useEffect(() => {
console.log('elem', elem);
})
const toggle = () => {
setModal(false);
}
return (
<div>
<Modal isOpen={modal} toggle={toggle}>
<ModalHeader toggle={toggle}>Modal title</ModalHeader>
<ModalBody>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={toggle}>Do Something</Button>{' '}
<Button color="secondary" onClick={toggle}>Cancel</Button>
</ModalFooter>
</Modal>
</div>
);
}
Instead of passing elem prop directly inside useState
do something like this.
const [modal, setModal] = useState(false)
useEffect(() => {
setModal(Boolean(elem)) // I suppose it is not boolean so make it boolean
},[elem])
I use reactstrap Modal but somehow when isOpen is true, the modal just appears as plain text instead of a box shown over the window. When I use the same Modal code to run a new component, the Modal is still rendered as happened so it is not the CSS. How should I modify my Modal
function App() {
const [people, setPeople] = useState(data);
const [modalOpen, setModalOpen] = useState(false);
const toggle = () => {
setModalOpen(!modalOpen);
console.log(modalOpen)
}
return (
<main>
<section className="container">
<h3>
{people.length} birthday today
</h3>
<List people={people} />
<button onClick={() => setPeople([])}>
Clear All
</button>
<button onClick={() => setModalOpen(!modalOpen)}>
Add birthday
</button>
<Modal isOpen={modalOpen} toggle={toggle} className="modal">
<ModalHeader toggle={toggle}>Modal title</ModalHeader>
<ModalBody>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={toggle}>Do Something</Button>{' '}
<Button color="secondary" onClick={toggle}>Cancel</Button>
</ModalFooter>
</Modal>
</section>
</main>
)
}
You have to import bootstrap stylesheet like this import "bootstrap/dist/css/bootstrap.min.css"; (and install bootstrap if you haven't) and remove modal class name from Modal component. Here's CSB example
I created a modal that opens when it has not been read yet and which no longer opens when it has been read. I have stored the value false in the localStorage and if it has been read it opens and then closes. I wish it would never open if it hasn't been read.
import React, { useEffect, useState } from "react";
import Loader from "react-loader-spinner";
export default function Modal() {
const [isOpen, setIsOpen] = useState(true);
useEffect(()=>{
const isRead = localStorage.getItem("value");
if (isRead){
setIsOpen(false)
} else if (!isRead){setIsOpen(true)};
},[])
return (
<>
{isOpen && (
<div>
<button
className="close" onClick={()=>{ setIsOpen(false) || localStorage.setItem("value", false)}}
/>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute
irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui
officia deserunt mollit anim id est laborum.
</p>
</div>
)}
{!isOpen && (
<Loader
className="spinner"
type="ThreeDots"
color="#F5F5F5"
height={100}
width={100}
timeout={1500}
/>
)}
</>
);
}
I have resolved my problem :
import React, { useEffect, useState } from "react";
import Loader from "react-loader-spinner";
export default function Modal() {
const [isOpen, setIsOpen] = useState(false);
useEffect(()=>{
const isRead = localStorage.getItem("value");
if (!isRead){
setIsOpen(true)
}
},[])
return (
<>
{isOpen && (
<div>
<button
className="close" onClick={()=>{ setIsOpen(false) || localStorage.setItem("value", true)}}
/>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute
irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui
officia deserunt mollit anim id est laborum.
</p>
</div>
)}
{!isOpen && (
<Loader
className="spinner"
type="ThreeDots"
color="#F5F5F5"
height={100}
width={100}
timeout={1500}
/>
)}
</>
);
}
The first problem is on this line
else if (!isRead){setIsOpen(true)}
Once isRead returns false i.e the modal was read and then you add the not operator it'll return true and that will set setIsOpen to true which opens the modal.
You can try this:
import React, { useEffect, useState } from "react";
import Loader from "react-loader-spinner";
export default function Modal() {
const [isOpen, setIsOpen] = useState(true);
useEffect(()=>{
const isRead = localStorage.getItem("value");
if (isRead){
setIsOpen(false)
}
},[])
return (
<>
{isOpen && (
<div>
<button
className="close" onClick={()=>{ setIsOpen(false) || localStorage.setItem("value", true)}}
/>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute
irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui
officia deserunt mollit anim id est laborum.
</p>
</div>
)}
{!isOpen && (
<Loader
className="spinner"
type="ThreeDots"
color="#F5F5F5"
height={100}
width={100}
timeout={1500}
/>
)}
</>
);
}
I used the reactstrap modal from https://reactstrap.github.io/components/modals/
import React from 'react';
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
class ModalExample extends React.Component {
constructor(props) {
super(props);
this.state = {
modal: false
};
this.toggle = this.toggle.bind(this);
}
toggle() {
this.setState({
modal: !this.state.modal
});
}
render() {
return (
<div>
<Button color="danger" onClick={this.toggle}>{this.props.buttonLabel}</Button>
<Modal isOpen={this.state.modal} fade={false} toggle={this.toggle} className={this.props.className}>
<ModalHeader toggle={this.toggle}>Modal title</ModalHeader>
<ModalBody>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={this.toggle}>Do Something</Button>{' '}
<Button color="secondary" onClick={this.toggle}>Cancel</Button>
</ModalFooter>
</Modal>
</div>
);
}
}
export default ModalExample;
the onclick function of my 'do something' button is a promise. And this function is defined in another component. I want to add busy cursor when the promise function is loading data. How to realize this? I have a scss file for my project.
Essentially, you'll need to add a CSS class to an element, execute your promise, and when it completes or fails, you remove the class. The class can look something like this.
.wait-cursor {
cursor: wait;
}