multiple-drawer reactJs in same page not working - javascript

I am intern ReactJs, how to use multiple-drawer reactJs in same page.
code my App.js file
App = () =>{
const [visible, setVisible] = useState(false);
const showDrawer = () => {
setVisible(true);
};
const onClose = () => {
setVisible(false);
};
return(
// drawer 1
<Button type="primary" className="btn-submit" onClick={this.showDrawer}>submit drawer 1</Button>
<Drawer className="modal-form"onClose={onClose} visible={visible}>
content
</Drawer>
// drawer 2
<Button type="primary" className="btn-submit" onClick={this.showDrawer}>submit drawer 2</Button>
<Drawer className="modal-form"onClose={onClose} visible={visible}>
content
</Drawer>
)
}
how can i click on the button tag to show the corresponding drawer!
pls! help me.

If these drawers contain different content then you will have to manage two state variables for each drawer to control the visibility of drawer.
App = () =>{
const [visibleDrawer1, setVisibleDrawer1] = useState(false);
const [visibleDrawer2, setVisibleDrawer2] = useState(false);
const showDrawer1 = () => {
setVisibleDrawer1(true);
};
const onCloseDrawer1 = () => {
setVisibleDrawer1(false);
};
const showDrawer2 = () => {
setVisibleDrawer2(true);
};
const onCloseDrawer2 = () => {
setVisibleDrawer2(false);
};
return(
// drawer 1
<Button type="primary" className="btn-submit"
onClick={this.showDrawer1}>submit drawer 1</Button>
<Drawer className="modal-form"onClose={onCloseDrawer1}
visible={visibleDrawer1}>
content
</Drawer>
// drawer 2
<Button type="primary" className="btn-submit"
onClick={this.showDrawer2}>submit drawer 2</Button>
<Drawer className="modal-form"onClose={onCloseDrawer2}
visible={visibleDrawer2}>
content
</Drawer>
)
}

Related

Display a notification that an item was successfully deleted

The site has a button for deleting an element (one element is deleted per button click).
Timing: the user presses the delete button -> a window opens with a warning and two buttons: cancel and confirm -> when the confirm button is pressed, the deletion process begins, which is accompanied by a scroll wheel. After deletion, the window closes and you can continue to work on the site.
I would like to display a notification after the window is closed that the item was removed successfully. Tell me how can I do it.
export function Delete() {
const [alertShown, setAlertShown] = useState(false);
const [alertLoading, setAlertLoading] = useState(false);
const onNo = () => {
setAlertShown(false);
};
const onYes = async () => {
setAlertLoading(true);
await deleteItem();
setAlertShown(false);
setAlertLoading(false);
};
return <ButtonGroup >
<div onClick={() => setAlertShown(true)}>
<DeleteForeverIcon/>
</div>
{alertShown && (
<Dialog open={onYes}>
{alertLoading
? <div ><Spinner/></div>
: <DialogActions >
<Button color="error" onClick={onNo}>Cancel</Button >
<Button onClick={onYes}>Confirm </Button >
</DialogActions>}
</Dialog>
)}
</ButtonGroup>
}
The easiest approach to implement notification is using setTimeout. You can try the below code snippet
export function Delete() {
const [alertShown, setAlertShown] = useState(false);
const [alertLoading, setAlertLoading] = useState(false);
const [notificationShown, setNotificationShown] = useState(false);
const onNo = () => {
setAlertShown(false);
};
const onYes = async () => {
setAlertLoading(true);
await deleteItem();
setAlertShown(false);
setAlertLoading(false);
//open the notification
setNotificationShown(true);
setTimeout(() => {
setNotificationShown(false);
}, 5000); //automatically close the notification after 5 seconds
};
return (
<ButtonGroup>
{notificationShown && <span>The item was removed successfully</span>}
<div onClick={() => setAlertShown(true)}>
<DeleteForeverIcon />
</div>
{alertShown && (
<Dialog open={onYes}>
{alertLoading ? (
<div>
<Spinner />
</div>
) : (
<DialogActions>
<Button color="error" onClick={onNo}>
Cancel
</Button>
<Button onClick={onYes}>Confirm </Button>
</DialogActions>
)}
</Dialog>
)}
</ButtonGroup>
);
}
The sandbox link

How to show modal based on what was clicked on the card [duplicate]

This question already has an answer here:
How do I use React Modal with a map function?
(1 answer)
Closed 6 months ago.
How can I show the modal only based on card was clicked?
I have this dynamic card. Once I clicked on a specific card, how can it show the modal with a title of the data's id? As of now, once I click on a card, it will only show the last id.
Main app
const [isOpen, setisOpen] = useState(false);
const handleOpen = (id) => {
console.log(id);
setOpen(true)
};
const handleClose = () => {
setisOpen(false);
};
....
{data.map((i) => (
<Grid
key={data.indexOf(i)}
>
<CardonClick={(e) => handleOpen(i.id)}>
<CardHeader title={i.title} />
</Card>
<Modal isOpen={isOpen} handleClose={handleClose} title={i.id}/> <-- display of the id here
</Grid>
))}
Modal reusable component
import {
Dialog,
DialogContent,
DialogContentText,
DialogTitle,
Divider,
Button,
DialogActions,
} from "#mui/material";
const Modal = ({ title, subtitle, children, isOpen, handleClose }) => {
return (
<Dialog open={isOpen} onClose={handleClose}>
<DialogTitle>{title}</DialogTitle>
<DialogContent>
<DialogContentText>{subtitle}</DialogContentText>
<Divider />
{children}
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="error">
No
</Button>
</DialogActions>
</Dialog>
);
};
export default Modal;
You can use useState hook and store the relevant data (id in your case) in handleOpen function. Then you can use that data in your modal. example:
const [isOpen, setisOpen] = useState(false);
const [currentModalId,setCurrentModalId]=useState("");
const handleOpen = (id) => {
console.log(id);
setCurrentModalId(id);
setOpen(true)
};
const handleClose = () => {
setisOpen(false);
};
And then use it:
...<Modal> <div> {id} </Modal>

JS: Problem with with displaying a select list in modal on page

I have a problem with displaying a list for user selection. When I open the page for the first time, it works correctly. But after I reload the page, the users "disappear" or are unloaded.
Before reload
After reload.
Here is the code I have.
My-page:
const Page = observer(() => {
const { project } = useContext(Context);
const [modalVisible, setModalVisible] = useState(false);
useEffect(() => {
fetchUsers().then((data) => project.setUsers(data));
}, []);
return (
<Container>
<Button onClick={() => setModalVisible(true)}>
ChooseUser
</Button>
<ChooseUser show={modalVisible} onHide={() => setModalVisible(false)} />
</Container>
);
});
export default Page;
Modal:
const ChooseUser = observer(({ show, onHide }) => {
const { project } = useContext(Context);
return (
<Modal show={show} onHide={onHide}>
<Form>
<Form.Select>
{/* The problem with this list */}
{project.users.map((user) =><option>{user.username}</option>)}
</Form.Select>
</Form>
</Modal>
);
});
Context creating in index.js:
export const Context = createContext(null);
ReactDOM.render(
<Context.Provider value={{
project: new ProjectStore(),
}}
>
<App />
</Context.Provider>,
document.getElementById('root'),
);
ProjectStore
export default class ProjectStore {
constructor() {
this._users = [];
makeAutoObservable(this);
}
setUsers(value) {
this._users = value;
}
get users() {
return this._users;
}
}
You might try Array.from(project.users).map((user) ... instead of project.users.map((user) ... and see if that helps.

React hook: How to call Modal component from another component in react

I am trying to create a modal that I can reuse/call from multiple components. I want the modal to display in app.js but the button call is on another component.
Once I am able to implement one, I can but button on other components and call same modal instead of having to create the same modal for each component
<div className="App">
<HeroSlider />
<HowItWorks />
<Modal />
<Footer />
</div>
The modal button is on this component(HeroSlider). Once its click it will call the modal component and display it in app.js
import React, { useState } from "react";
import Header from './Header'
function HeroSlider(props) {
const [show, setShow] = useState(false);
const modalShow = () => setShow(true);
const openIsAccount = () => {
}
return (
<div className="jumbotron" id="jumbotron2" >
<button type="button" className="btn btn-primary" id="shoutBtn" onClick={modalShow}><span>Get Started</span>
</button>
</div>
);
}
export default HeroSlider;
Here is the Modal.js
const IsAccountOpen = (props) => {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<>
<Modal show={props.show} onHide={handleClose} backdrop="static" keyboard={false}>
<Modal.Header closeButton>
<Modal.Title>Modal title</Modal.Title>
</Modal.Header>
<Modal.Body>
I will not close
</Modal.Body>
</Modal>
</>
);
};
export default IsAccountOpen
You need to add a function in the app.js to handle the click on the button, so the function will change the state show to true, and you will pass the state to your modal, like this:
App.js
[showState, setShowState] = useState(false)
buttonClickedHandler = () => {
setShowState((showState) => showState = !showState )
}
<div className="App">
<HeroSlider buttonClicked={buttonClickedHandler} />
<HowItWorks />
<Modal show={showState} buttonClicked={buttonClickedHandler} />
<Footer />
</div>
HeroSlider.js
import React, { useState } from "react";
import Header from './Header'
function HeroSlider(props) {
const [show, setShow] = useState(false);
const modalShow = () => setShow(true);
const openIsAccount = () => {
}
return (
<div className="jumbotron" id="jumbotron2" >
<button type="button" className="btn btn-primary" id="shoutBtn" onClick={props.buttonClicked}><span>Get Started</span>
</button>
</div>
);
}
export default HeroSlider;
IsAccountOpen.js
const IsAccountOpen = (props) => {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<>
<Modal show={props.show} onHide={props.buttonClicked} backdrop="static" keyboard={false}>
<Modal.Header closeButton>
<Modal.Title>Modal title</Modal.Title>
</Modal.Header>
<Modal.Body>
I will not close
</Modal.Body>
</Modal>
</>
);
};
export default IsAccountOpen
I think the best solution is to use redux, because you will need to access and update the state from different components, you shouldn't use context API because the state changes frequently and you will hit the performance.
You'll need to extract the state to App level, so that this can be shared to components. You can do this with useState, or using context & custom hooks if you want to make it very clean. But do it with useState on first.
HeroSlider should receive modalShow function in it's props.
Modal.js should receive the show state as props.

how to prevent element re-rendering

I have to show a PDF file on a page and it works well but whenever I open or close the modal the PDF is re-rendered.
import { documentActions } from '../_actions'
export default function DocPreview() {
const document = useSelector(({ document }) => document)
const [show, setShow] = useState(false)
const dispatch = useDispatch()
useEffect(() => dispatch(documentActions.getDocumentContent('someDocId')), [dispatch])
return <main>
{document.loaded && <embed src={URL.createObjectURL(document.data)} type='application/pdf' />}
<button onClick={() => setShow(true)}>Sign document</button>
<Modal show={show} onHide={() => setShow(false)}>
<button className='btn btn-secondary' onClick={() => setShow(false)}>Close</button>
</Modal>
</main>
}
You can make the pdf document it's own component and only re render when document changes:
const Pdf = React.memo(function Pdf({ document }) {
document.loaded && (
<embed
src={URL.createObjectURL(document.data)}
type="application/pdf"
/>
);
});
In DocPreview
<main>
<Pdf document={document} />

Categories

Resources