How to clear state on Dialog close React? - javascript

I am using https://react-spectrum.adobe.com/react-spectrum/Dialog.html and whenever I close the dialog and reopen it the value I type does not default back to the initial state. How can I render Dialog on close to reset all states within the dialog?
import {
ActionButton,
Button,
ButtonGroup,
Content,
Dialog,
DialogTrigger,
Divider,
Header,
Heading,
Text,
TextField,
} from "#adobe/react-spectrum";
import { useState } from "react";
export const DialogBox = () => {
const [value, setValue] = useState("");
return (
<DialogTrigger>
<ActionButton>Check connectivity</ActionButton>
{(close) => (
<Dialog>
<Heading>Internet Speed Test</Heading>
<Header>Connection status: Connected</Header>
<Divider />
<Content>
<TextField value={value} onChange={setValue} />
</Content>
<ButtonGroup>
<Button variant="secondary" onPress={close}>
Cancel
</Button>
<Button variant="cta" onPress={close}>
Confirm
</Button>
</ButtonGroup>
</Dialog>
)}
</DialogTrigger>
);
};

Run setValue('') before closing
import {
ActionButton,
Button,
ButtonGroup,
Content,
Dialog,
DialogTrigger,
Divider,
Header,
Heading,
Text,
TextField,
} from "#adobe/react-spectrum";
import { useState } from "react";
export const DialogBox = () => {
const [value, setValue] = useState("");
return (
<DialogTrigger>
<ActionButton>Check connectivity</ActionButton>
{(close) => {
const onClose = () => {
setValue('')
close()
}
return (
<Dialog>
<Heading>Internet Speed Test</Heading>
<Header>Connection status: Connected</Header>
<Divider />
<Content>
<TextField value={value} onChange={setValue} />
</Content>
<ButtonGroup>
<Button variant="secondary" onPress={onClose }>
Cancel
</Button>
<Button variant="cta" onPress={onClose }>
Confirm
</Button>
</ButtonGroup>
</Dialog>
)
}
)}
</DialogTrigger>
);
};

#Konrad Linkowski 's is good,
but I would recommend a better structure.
You can read from their docs about: handling events.
In the event handling you can add the setValue(''):
const cancel = (close) => {
setValue('');
close();
};

Related

How can I pass a function to the child component?

I have this component with a modal for confirmation when deleting an item. How can I pass the function to the child component so that once I click the button Agree, it will trigger this function for delete.
The function to delete an item:
const deleteProduct = async (id) => {
const productDoc = doc(db, "products", id);
await deleteDoc(productDoc);
};
The Dialog:
<Modal
title="Confirmation"
subtitle={sample}
isOpen={isOpen}
handleClose={handleClose}
/>
The Reusable component:
import {
Dialog,
DialogContent,
DialogContentText,
DialogTitle,
Divider,
Button,
DialogActions,
} from "#mui/material";
const Modal = ({ title, subtitle, children, isOpen, handleClose }) => {
const handleConfirm = () => {
alert("You Agreed!");
handleClose();
};
return (
<Dialog open={isOpen} onClose={handleClose}>
<DialogTitle>{title}</DialogTitle>
<DialogContent>
<DialogContentText>{subtitle}</DialogContentText>
<Divider />
{children}
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="error">
Cancel
</Button>
<Button onClick={handleConfirm} color="primary">
Agree
</Button>
</DialogActions>
</Dialog>
);
};
export default Modal;
Simply pass the function and productId as props to Modaland because the function is asynchronous, you have to make the handleConfirm asynchronous as well.
The Dialog:
<Modal
productId={id}
title="Confirmation"
subtitle={sample}
isOpen={isOpen}
deleteProductCallback={deleteProduct}
handleClose={handleClose}
/>
The Reusable component:
import {
Dialog,
DialogContent,
DialogContentText,
DialogTitle,
Divider,
Button,
DialogActions,
} from "#mui/material";
const Modal = ({ productId,title, subtitle, children, isOpen, handleClose ,deleteProductCallback}) => {
const handleConfirm = async() => {
alert("You Agreed!");
await deleteProductCallback(productId);
handleClose();
};
return (
<Dialog open={isOpen} onClose={handleClose}>
<DialogTitle>{title}</DialogTitle>
<DialogContent>
<DialogContentText>{subtitle}</DialogContentText>
<Divider />
{children}
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="error">
Cancel
</Button>
<Button onClick={handleConfirm} color="primary">
Agree
</Button>
</DialogActions>
</Dialog>
);
};
Update the reusable component to accept an onConfirm prop and pass deleteProduct in as that argument. I've changed handleClose to onClose here for consistency.
<Modal
title="Confirmation"
subtitle={sample}
isOpen={isOpen}
onClose={handleClose}
onConfirm={() => deleteProduct(id)}
/>
// ...
const Modal = ({ title, subtitle, children, isOpen, onClose, onConfirm }) => {
const handleConfirm = () => {
alert("You Agreed!");
onConfirm();
onClose();
};
// ...
You can pass the deleteProduct function and the id as props to the Modal Components like bellow:
The Dialog:
<Modal
title="Confirmation"
subtitle={sample}
isOpen={isOpen}
id={id}
handleClose={handleClose}
deleteProduct={deleteProduct}
/>
The Reusable component:
import {
Dialog,
DialogContent,
DialogContentText,
DialogTitle,
Divider,
Button,
DialogActions,
} from "#mui/material";
const Modal = ({ title, subtitle, children, isOpen, id, handleClose, deleteProduct }) => {
const handleConfirm = () => {
alert("You Agreed!");
handleClose();
deleteProduct(id)
};
return (
<Dialog open={isOpen} onClose={handleClose}>
<DialogTitle>{title}</DialogTitle>
<DialogContent>
<DialogContentText>{subtitle}</DialogContentText>
<Divider />
{children}
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="error">
Cancel
</Button>
<Button onClick={handleConfirm} color="primary">
Agree
</Button>
</DialogActions>
</Dialog>
);
};
export default Modal;

Material-UI Dialog Reusable Component Not Working but no error in the console and app does not crash

This is my 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">
Close
</Button>
</DialogActions>
</Dialog>
);
};
export default Modal;
Parent component where I use this here:
const [isOpen, setisOpen] = useState(false);
const [isOpenDialog, setIsOpenDialog] = useState(false);
const handleDialogOpen = () => {
setisOpen(true);
};
const handleDialogClose = () => {
setisOpen(false);
};
const handleOpen = () => {
setIsOpenDialog(true);
};
const handleClose = () => {
setIsOpenDialog(false);
};
<Modal
title="confirmation"
isOpen={isOpen}
children={sample}
handleClose={handleDialogClose}
/>
<Button
color="error"
onClick={
() => handleDialogOpen}
>
Delete
</Button>
It does not show any error in the console and the app does not crash. How can I fix this? Also how can I add a button where the user can say yes since at the moment the modal only have a buttin to close it
There's a lot to unpack here. Here's a solution:
import {
Dialog,
DialogContent,
DialogContentText,
DialogTitle,
Divider,
Button,
DialogActions
} from "#mui/material";
const Modal = ({ title, subtitle, children, isOpen, handleClose }) => {
const handleConfirm = () => {
alert("You Agreed!");
handleClose();
};
return (
<Dialog open={isOpen} onClose={handleClose}>
<DialogTitle>{title}</DialogTitle>
<DialogContent>
<DialogContentText>{subtitle}</DialogContentText>
<Divider />
{children}
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="error">
Cancel
</Button>
<Button onClick={handleConfirm} color="primary">
Agree
</Button>
</DialogActions>
</Dialog>
);
};
export default Modal;
Here's the parent:
import Modal from "./modal";
import { useState } from "react";
import { Button } from "#mui/material";
export default function App() {
const [isOpen, setisOpen] = useState(false);
const handleOpen = () => {
setisOpen(true);
};
const handleClose = () => {
setisOpen(false);
};
return (
<div className="App">
<Modal title="confirmation" isOpen={isOpen} handleClose={handleClose} />
<Button color="primary" onClick={handleOpen}>
I Agree
</Button>
</div>
);
}
Here's the sandbox:

React Material Ui Dialog not Displaying Correct Values

I am trying to play with react material ui dialog boxes and I noticed a problem or maybe I am doing it wrong. I've an object a and when I click on the a button in list, it should display the respective id number but it is always displaying the id number of the last id,index instead, what is the issue? Is it because i am calling them in a loop and all three dialogue boxes are being called at the same time? what should I do to basically show the respective id with every button.
...
export default function AlertDialog() {
const [open, setOpen] = React.useState(false);
const a = [{ id: 1 }, { id: 2 }, { id: 3 }];
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<>
<List>
{a.map(({ id }, index) => {
return (
<>
<ListItem button onClick={handleClickOpen}>
{id}
</ListItem>
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">{id}</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description" />
</DialogContent>
</Dialog>
</>
);
})}
</List>
</>
);
}
...
my sample https://codesandbox.io/s/material-demo-k5s8k?file=/demo.js
All 3 dialogs are being opened, because you are controlling all 3 of them using the same open variable. The last dialog is just the one on top. If you look at the DOM via the browser developer tools you will see that all 3 are there.
You can fix this by managing the open state in a way that allows you to tell which id is open.
One way is to set into state the id of the dialog that is open:
import React from "react";
import Dialog from "#material-ui/core/Dialog";
import DialogContent from "#material-ui/core/DialogContent";
import DialogContentText from "#material-ui/core/DialogContentText";
import DialogTitle from "#material-ui/core/DialogTitle";
import { List, ListItem } from "#material-ui/core";
export default function AlertDialog() {
const [openId, setOpenId] = React.useState(null);
const a = [{ id: 1 }, { id: 2 }, { id: 3 }];
const handleClickOpen = id => {
setOpenId(id);
};
const handleClose = () => {
setOpenId(null);
};
return (
<>
<List>
{a.map(({ id }, index) => {
return (
<>
<ListItem button onClick={() => handleClickOpen(id)}>
{id}
</ListItem>
<Dialog
open={openId === id}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">{id}</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description" />
</DialogContent>
</Dialog>
</>
);
})}
</List>
</>
);
}

How to call dialog box from another file in React

I am very new to React so this may seem a little trivial. I have a delete icon in one file which when clicked, I am trying to program a confirmation dialog box. Using the source of their website: https://material-ui.com/components/dialogs/. My file is comprises of a listview:
ListView:
import React from 'react';
import PropTypes from 'prop-types';
import { List, ListItem, ListItemText, ListItemAvatar, Avatar, ListItemSecondaryAction, IconButton } from '#material-ui/core';
import DeleteIcon from '#material-ui/icons/Delete';
import AlertDialog from './AlertDialog'
// Import CSS
import './ListViewer.css'
export function ListViewer({ objects}) {
return (
<div className='list-viewer'>
<List>
<ListItem alignItems="center" divider key={obj.id}>
<ListItemText primary={objects.name} />
<ListItemSecondaryAction>
<IconButton edge="end" aria-label="delete" onClick={handleClickOpen()}>
<DeleteIcon />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
</List>
</div>
);
}
AlertDialog.js:
import React from 'react';
import Button from '#material-ui/core/Button';
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';
import DialogTitle from '#material-ui/core/DialogTitle';
export default function AlertDialog() {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
{/* <Button variant="outlined" color="primary" onClick={handleClickOpen}>
Open alert dialog
</Button> */}
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">{"Are you sure you want to delete this object?"}</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
Deleting this object will permanently remove it
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Cancel
</Button>
<Button onClick={handleClose} color="primary" autoFocus>
Delete
</Button>
</DialogActions>
</Dialog>
</div>
);
}
As you can see in AlertDialog, there was initially a button which triggers the dialog to open. Instead from my other file, when the delete icon is clicked, I am trying to trigger the dialog. How can I do this? I have imported AlertDialog and AlertDialog.handleClickOpen but this does not work as handleClickOpen is not a function
You can pass open and onClose via props into AlertDialog.
function AlertDialog(props) {
const { open, onClose } = props
return (
<Dialog
open={open}
onClose={onClose}
>
{/* Dialog content */}
</Dialog>
Then, simply use it in ListView:
function ListView() {
const [dialogIsOpen, setDialogIsOpen] = React.useState(false)
const openDialog = () => setDialogIsOpen(true)
const closeDialog = () => setDialogIsOpen(false)
return (
<div className='list-viewer'>
<List>{/* Now you can set dialogIsOpen here */}</List>
<AlertDialog open={dialogIsOpen} onClose={closeDialog} />
</div>
)
}
There are a few steps how I would do it the first is that I would do instead of a open and close function I would do one as this:
const toggleDialog = useCallback(() => {
setOpen(!open);
}, [open]);
The useCallback function makes it that it only creates a new function when the parameter in the [] changes, means when open changes.
Sadly #Code-Apprentice was faster and metioned the rest to it.
<IconButton edge="end" aria-label="delete" onClick={handleClickOpen()}>
The onClick handler here must be in the same class that renders the <IconButton>. Also, remove the parentheses to set the onClick prop to the function instead of its return value:
onClick={handleClickOpen}

My modal doesn't show when I click a button

Here I have my modal component. I am making an app that I want a button to open this modal that I use in multiple places like opening a preview or deleting options.
import React from 'react';
import ReactDOM from 'react-dom';
import { CSSTransition } from 'react-transition-group';
import Backdrop from '../Backdrop/Backdrop';
import '../Modal/Modal.css';
const ModalOverlay = (props) => {
const content = (
<div className={`modal ${props.className}`} style={props.style}>
<header className={`modal__header ${props.headerClass}`}>
<h2>{props.header}</h2>
</header>
<form
onSubmit={
props.onSubmit ? props.onSubmit : (event) => event.preventDefault()
}
>
<div className={`modal__content ${props.contentClass}`}>
{props.children}
</div>
<footer className={`modal__footer ${props.footerClass}`}>
{props.footer}
</footer>
</form>
</div>
);
return ReactDOM.createPortal(content, document.getElementById('modal-hook'));
};
const Modal = (props) => {
return (
<React.Fragment>
{props.show && <Backdrop onClick={props.onCancel} />}
<CSSTransition
in={props.show}
mountOnEnter
unmountOnExit
timeout={200}
classNames="modal"
>
<ModalOverlay {...props} />
</CSSTransition>
</React.Fragment>
);
};
export default Modal;
And here I use this modal for showing up deleting options.
const DocumentItem = (props) => {
const [showConfirmModal, setShowConfirmModal] = useState(false);
const showDeleteWarningHandler = () => {
setShowConfirmModal(true);
};
const calcelDeleteHandler = () => {
setShowConfirmModal(false);
};
const confirmDeleteHandler = () => {
setShowConfirmModal(false);
console.log('Delete!');
};
return (
<React.Fragment>
<Modal
show={showConfirmModal}
onCancel={calcelDeleteHandler}
header="Are you sure?"
footerClass="document-item__modal-actions"
footer={
<React.Fragment>
<Button inverse onClick={calcelDeleteHandler}>
CANCEL
</Button>
<Button danger onClick={confirmDeleteHandler}>
DELETE
</Button>
</React.Fragment>
}
>
<p>
Do you want to proceed and delete this document? Please note that it
can't be undone thereafter.
</p>
</Modal>
</React.Fragment>
);
};
I don't understand why my screen goes all black, transparent but my modal doesn't show.
How can I fix this problem?

Categories

Resources