📅 September 12, 2019
👷 Chris Power
I’m working on a side project in React with Redux and Material UI. I love how snackbars look, and I wanted to create an easy system for displaying them throughout my application. If you’ve ever worked in Rails, picture the way you display flash
messages. I wanted something simple like that amazing Rails feature.
From the Material Design Guidelines: “Snackbars provide brief messages about app processes at the bottom of the screen”.
The ☝ ️guidelines also specify the way you’re supposed to implement snackbars: “Snackbars inform users of a process that an app has performed or will perform. They appear temporarily, towards the bottom of the screen. They shouldn’t interrupt the user experience, and they don’t require user input to disappear”. This is the perfect use case to show a user when they completed a successful action on your application!
Material UI is a component framework for React based on Material IO guidelines. They have an excellent snackbar component that we can leverage to show snackbar notifications to our users.
I wanted to use snackbars all over my application. There are many places where a user can take an action that results in a snackbar appearing. I didn’t want to instantiate a new Snackbar component for every single component that requires one to be displayed. Here is a quick example of one snackbar in my app:
Thankfully I am using React, with Redux. And I love using Redux as often as possible to solve my state issues. There is a pattern that I love with redux that I like to call the “redux ui” pattern. Basically I use redux to store at least some of my UI state throughout the app. This makes global UI changes (think users specifying dark mode in their apps) easy to store and propagate throughout your app.
// reducers/uiReducer.js
const uiReducer = (state = {}, action) => {
switch (action.type) {
case "SNACKBAR_SUCCESS":
return {
...state,
successSnackbarOpen: true,
successSnackbarMessage: action.message
};
case "SNACKBAR_CLEAR":
return {
...state,
successSnackbarOpen: false,
errorSnackbarOpen: false,
infoSnackbarOpen: false
};
default:
return state;
}
};
export default uiReducer;
☝️ Will give us some structure for displaying a “success” snackbar, along with clearing out all possible snackbars we may want to create (including error and info… just in case).
// actions/snackbarActions.js
export const showSuccessSnackbar = message => {
return dispatch => {
dispatch({ type: "SNACKBAR_SUCCESS", message });
};
};
export const clearSnackbar = () => {
return dispatch => {
dispatch({ type: "SNACKBAR_CLEAR" });
};
};
clearSnackbar()
function to clear itself// components/SuccessSnackbar.js or whatever you wanna call it
import { useDispatch, useSelector } from "react-redux";
import Snackbar from "@material-ui/core/Snackbar";
import IconButton from "@material-ui/core/IconButton";
import { Icon } from "@material-ui/core";
import { clearSnackbar } from "../../store/actions/snackbarActions";
export default function SuccessSnackbar() {
const dispatch = useDispatch();
const { successSnackbarMessage, successSnackbarOpen } = useSelector(
state => state.ui
);
function handleClose() {
dispatch(clearSnackbar());
}
return (
<Snackbar
anchorOrigin={{
vertical: "bottom",
horizontal: "left"
}}
open={successSnackbarOpen}
autoHideDuration={4000}
onClose={handleClose}
aria-describedby="client-snackbar"
message={
<span id="client-snackbar">
<Icon>check_circle</Icon>
{successSnackbarMessage}
</span>
}
action={[
<IconButton
key="close"
aria-label="close"
color="inherit"
onClick={handleClose}
>
<Icon>close</Icon>
</IconButton>
]}
/>
);
}
in ☝️ note that we are using the clearSnackbar()
function when the snackbar calls handleClose
. Note, handleClose
is called after the timeout specified, so the snackbar will automatically call this function after a certain amount of time.
App.js
file. This allows you to display a snackbar ANYWHERE in your app using redux:return (
<div>
<SuccessSnackbar />
<Router>
//App stuff goes in here
</Router>
</div>
);
showSuccessSnackbar()
function with your message whenever you want to show a success snackbar.dispatch(showSuccessSnackbar("Success!"));
Success! Now you can display a snackbar anywhere in your React app using Redux. You are such a smart developer, aren’t you? 😄
I found this to be a fun and interesting pattern to use when you want to globally display snackbars, or alerts, or anything in your React application. It’s straightforward enough for any developer to understand, and its extensible to add anything: alerts, snackbars, messages, etc…
We're trusted by large, medium, and small companies all over the world
Have something you're working on?
Tell Us About It