admin管理员组文章数量:1335181
Material ui dialog closes the snackbar along with it.
This is a weird problem so I created a demo to demonstrate the issue:
I am passing states from parent to child so the parent state can update based on the child
<Child openDialog={openDialog} setOpenDialog={setOpenDialog} />
In the child, I am using these as below
export default function Child({openDialog, setOpenDialog}) {
The button in the child is supposed to close only the dialog but it closes snackbar too.
<button
onClick={() => dialogClick()}
>Click this dialog button
</button>
Line 12 in the child has setOpenSnack("true");
This only works when I ment out line 13 setOpenDialog(false);
const dialogClick = (event) => {
setMsg("This should close dialog only and open the snackbar");
setOpenSnack(true);
setOpenDialog(false);
};
This behavior is only when I split it into child and parent.
In short, why does setOpenSnack(true);
in the child not work?
Material ui dialog closes the snackbar along with it.
This is a weird problem so I created a demo to demonstrate the issue:
https://codesandbox.io/s/react-hooks-counter-demo-v20w3
I am passing states from parent to child so the parent state can update based on the child
<Child openDialog={openDialog} setOpenDialog={setOpenDialog} />
In the child, I am using these as below
export default function Child({openDialog, setOpenDialog}) {
The button in the child is supposed to close only the dialog but it closes snackbar too.
<button
onClick={() => dialogClick()}
>Click this dialog button
</button>
Line 12 in the child has setOpenSnack("true");
This only works when I ment out line 13 setOpenDialog(false);
const dialogClick = (event) => {
setMsg("This should close dialog only and open the snackbar");
setOpenSnack(true);
setOpenDialog(false);
};
This behavior is only when I split it into child and parent.
In short, why does setOpenSnack(true);
in the child not work?
-
Snackbar
'sopen
prop expects boolean. You should usesetOpenSnack(true)
instead ofsetOpenSnack("true")
. – bertdida Commented Aug 8, 2020 at 2:20 - @bertdida Sure. I updated the demo. That does not fix the issue. Good catch though – Kal Commented Aug 8, 2020 at 2:23
- Basically you want to show the snackbar when the dialog is closed? – bertdida Commented Aug 8, 2020 at 2:24
- @bertdida I have simplified to show the issue but yes, the snackbar should not disappear when dialog is closed. They are separate elements. Seems like a bug but not sure. – Kal Commented Aug 8, 2020 at 2:25
-
Your
Snackbar
is sitting insideDialog
. When theDialog
unmounts/hidden, yourSnackbar
will also be unmounted. – bertdida Commented Aug 8, 2020 at 2:32
3 Answers
Reset to default 3Move your Snackbar
to your parent ponent so that it's not dependent on Dialog
's lifecycle.
App.js
import DialogBody from "./child";
function App() {
const [openDialog, setOpenDialog] = useState(false);
const [openSnack, setOpenSnack] = useState(false);
const [msg, setMsg] = useState("nothing");
function doApiCall(formData) {
// do your API calls here
console.log(formData);
// when done hide dialog, show snackbar
setOpenDialog(false);
setOpenSnack(true);
}
const fireOnClick = (event) => {
setMsg("you clicked a button");
setOpenDialog(true);
};
const handleCloseSnack = (event, reason) => {
if (reason === "clickaway") {
return;
}
setOpenSnack(false);
};
function Alert(props) {
return <MuiAlert elevation={6} variant="filled" {...props} />;
}
return (
<div className="App">
<h3>click button below to open dialog</h3>
<button onClick={() => fireOnClick()}>Click me</button>
<Dialog open={openDialog}>
<DialogTitle>This is a dialog</DialogTitle>
<DialogBody doApiCall={doApiCall} />
</Dialog>
<Snackbar
open={openSnack}
autoHideDuration={6000}
onClose={handleCloseSnack}
>
<Alert onClose={handleCloseSnack} severity="error">
{msg}
</Alert>
</Snackbar>
</div>
);
}
Child.js
export default function DialogBody({ doApiCall }) {
const [name, setName] = React.useState("");
function onChange(event) {
setName(event.target.value);
}
return (
<div>
<input type="text" value={name} onChange={onChange} />
<button onClick={() => doApiCall({ name })}>
Click this dialog button
</button>
</div>
);
}
Our DialogBody
ponent only accepts a prop called doApiCall
from our parent, which is invoked by clicking the Click this dialog button
.
doApiCall
might be an asynchronous call to your backends API which when resolves will hide the dialog and sets the snackbar to open.
When the dialog is closed, the Child ponent is dismantled. This justifies the disappearance of the Snack. Try this to see:
index.js
import React, { useState } from "react";
import ReactDOM from "react-dom";
import DialogTitle from "@material-ui/core/DialogTitle";
import Dialog from "@material-ui/core/Dialog";
import Child from "./child";
import Snackbar from "@material-ui/core/Snackbar";
import MuiAlert from "@material-ui/lab/Alert";
import "./styles.css";
function App() {
const [msg, setMsg] = useState("nothing");
const [openSnack, setOpenSnack] = useState(false);
const [openDialog, setOpenDialog] = useState(false);
//Close snackbar except when clickaway
const fireOnClick = (event) => {
setMsg("you clicked a button");
setOpenDialog(true);
//setOpenSnack(true);
};
const snackState = (value) => {
setOpenSnack(value)
}
const snackMessage = (value) => {
setMsg(value)
}
const handleCloseSnack = (event, reason) => {
if (reason === "clickaway") {
return;
}
setOpenSnack(false);
};
function Alert(props) {
return <MuiAlert elevation={6} variant="filled" {...props} />;
}
const closeDialogOnly = (event) => {
setMsg("you closed dialog only");
setOpenDialog(false);
};
return (
<div className="App">
<h3>click button below to open dialog</h3>
<button onClick={() => fireOnClick()}>Click me</button>
<Dialog onClose={closeDialogOnly} open={openDialog}>
<DialogTitle>This is a dialog</DialogTitle>
<Child snackbarStat={snackState} snackMessage={snackMessage} setOpenDialog={setOpenDialog} />
</Dialog>
<Snackbar
open={openSnack}
autoHideDuration={6000}
onClose={handleCloseSnack}
>
<Alert onClose={handleCloseSnack} severity="error">
{msg}
</Alert>
</Snackbar>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
child.js
import React from "react";
export default function Child({ snackbarStat, setOpenDialog, snackMessage }) {
const dialogClick = (event) => {
snackMessage("snackMessage")
snackbarStat(true);
setOpenDialog(false);
};
return (
<div className="child">
<button onClick={() => dialogClick()}>Click this dialog button</button>
<p>
{" "}
Clicking the button should close dialog but why is it closing the
snackbar also? <br />
The snack bar opens for one second and disappears.
<br />
setOpenSnack("true") lines is useless when dialog is false.
</p>
</div>
);
}
You have to place the Snackbar
in the parent ponent because when placing it in child ponent, it will disappear whenever the child is unmounted
Moreover, if you want to set the message, just pass the setMsg
to the child ponent and do the job
export default function Child({
openDialog,
setOpenDialog,
setMsg,
setOpenSnack
}) {
const dialogClick = (event) => {
setMsg("you closed from CHILD");
setOpenSnack(true);
setOpenDialog(false);
};
return (
<div className="child">
<button onClick={() => dialogClick()}>Click this dialog button</button>
<p>
...
</p>
</div>
);
}
本文标签: javascriptReact Material UISnackbar closes when Dialog closes but its not supposed toStack Overflow
版权声明:本文标题:javascript - React Material UI - Snackbar closes when Dialog closes but its not supposed to - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742382573a2464386.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论