I am using MaterialUi Snackbar with Slide
transition.
Expected Behaviour: Snackbar should slide in the provided direction and retreat on close.
This code is working.
Here’s the code:
import React, { useEffect, useState } from "react";
import Snackbar from "@mui/material/Snackbar";
import Slide from "@mui/material/Slide";
import Alert from "@mui/material/Alert";
const Transition = (newprops) => {
console.log("CustomMUISnackBar Transition props: ", newprops);
return <Slide {...newprops} direction="up" />;
};
function CustomMUISnackBar(props) {
const [open, setOpen] = useState(false);
useEffect(() => {
setOpen(props.open);
}, [props.open]);
return (
<Snackbar
autoHideDuration={1000}
TransitionComponent={Transition}
anchorOrigin={{ vertical: "top", horizontal: "center" }}
open={open}
onClose={() => {
setOpen(false);
props.onClose();
}}
key="Slide"
>
<Alert
onClose={() => {
setOpen(false);
props.onClose();
}}
severity="success"
sx={{ width: "100%" }}
>
<i style={{ color: "blue" }}>{props.updatedUserName}</i>'s details
updated!
</Alert>
</Snackbar>
);
}
export default CustomMUISnackBar;
But if I place Transition
function inside the functional component’s body then only the first part of the Slide
works as in it shows the snackbar opening with sliding but disappears without sliding.
function CustomMUISnackBar(props) {
const [open, setOpen] = useState(false);
const Transition = (newprops) => {
console.log("CustomMUISnackBar Transition props: ", newprops);
return <Slide {...newprops} direction="up" />;
};
return ();
}
export default CustomMUISnackBar;
It only happens when I use the Snackbar in a separate Component.js and then use it somewhere. If I use it directly it works whether I place the Transition
function inside the component or outside it.
Below code works for both buttons:
import React, { useState } from "react";
import Snackbar from "@mui/material/Snackbar";
import Slide from "@mui/material/Slide";
import Alert from "@mui/material/Alert";
const OutsideTransition = (tprops) => {
console.log("Outside Transition props: ", tprops);
return <Slide {...tprops} direction="up" />;
};
function CustomMUISnackBar(props) {
const [state, setState] = useState({
open: false,
transition: undefined
});
const InsideTransition = (tprops) => {
console.log("Outside Transition props: ", tprops);
return <Slide {...tprops} direction="up" />;
};
return (
<div>
<Snackbar
autoHideDuration={1000}
TransitionComponent={state.transition}
anchorOrigin={{ vertical: "top", horizontal: "center" }}
open={state.open}
onClose={() => setState({ ...state, open: false })}
key={state.transition?.name}
>
<Alert
onClose={() => setState({ ...state, open: false })}
severity="success"
>
<i style={{ color: "blue" }}>"Update Success!"</i>'s details updated!
</Alert>
</Snackbar>
<button
onClick={() => setState({ open: true, transition: OutsideTransition })}
>
SanckBar OutsideTransition
</button>
<button
onClick={() => setState({ open: true, transition: InsideTransition })}
>
SanckBar InsideTransition
</button>
</div>
);
}
export default CustomMUISnackBar;
If I use class Component in a separate component.js file, then also it works as expected.
This code works:
import React, { useEffect, useState } from "react";
import Snackbar from "@mui/material/Snackbar";
import Slide from "@mui/material/Slide";
import Alert from "@mui/material/Alert";
const Transition = (newprops) => {
console.log("CustomMUISnackBar Transition props: ", newprops);
return <Slide {...newprops} direction="up" />;
};
class CustomMUISnackBarClass extends React.Component {
constructor(props) {
super(props);
this.state = { open: props.open };
}
TransitionMethod = (newprops) => {
console.log("CustomMUISnackBar Transition props: ", newprops);
return <Slide {...newprops} direction="up" />;
};
render() {
return (
<Snackbar
autoHideDuration={1000}
TransitionComponent={this.TransitionMethod}
anchorOrigin={{ vertical: "top", horizontal: "center" }}
open={this.state.open}
onClose={() => {
this.setState({ open: false });
this.props.onClose();
}}
key="Slide"
>
<Alert
onClose={() => {
this.setState({ open: false });
this.props.onClose();
}}
severity="success"
sx={{ width: "100%" }}
>
<i style={{ color: "blue" }}>{this.props.updatedUserName}</i>'s
details updated!
</Alert>
</Snackbar>
);
}
}
export default CustomMUISnackBarClass;
Above code works even if TransitionComponent={this.TransitionMethod}
is replaced with TransitionComponent={Transition}
.
So, my question is how the functionality is getting differed in functional and class component. What is changing if a function is declared inside a functional component or outside as compared to behaviour when a functional component is defined in a component.js
file?
Here’s the code at codesandbox: https://codesandbox.io/s/transitionsnackbar-eillp. Wait for few seconds before clicking on other buttons.