What We’re Building

Setup/Dependencies

This post assumes you already have a React app set up with @material-ui/core 1.0.0+ and @material-ui/icons 1.0.0+ installed as dependencies.

Creating the Context

First, we need to create our Context API provider and consumer components. The provider provides the state of our snackbar, as well as some functions for manipulating that state, to all consumers. This allows all child components to access and manipulate the provider’s state no matter how deep they are within the component hierarchy. No prop drilling required!

The first step is creating a context by calling React.createContext(). The object returned contains two properties, Provider and Consumer. We use these to build out the components that will manage and interact with the snackbar’s state.

From here on out, when I use the terms “provider” and “consumer”, I’m referring to the SharedSnackbarProvider and SharedSnackbarConsumer components from this section.

As you can see, our provider is a pretty standard component. In its render function, we render a SharedSnackbarContext.Provider component with a value prop. The object passed to the value prop is what consumers will be able to access so they can interact with our snackbar. For lack of a better term, this is the API for our shared snackbar component.

Take note of the TODO on line 41. Eventually we’ll be rendering the actual snackbar within the context provider’s render function as a sibling to its children. This ensures that when the provider is rendered, all children will be using the same exact snackbar component.

Creating the Shared Snackbar Component

Now we need to build the presentation component responsible for rendering the snackbar UI based on the state of the provider. This component will use the consumer to access the properties it needs for rendering.

Here we’ve built a component that renders the snackbar UI in a function within the SharedSnackbarConsumer component. The argument to the function is the value prop object we exposed from our provider. As a result, when the state of the provider is updated, it will trigger the snackbar component to rerender.

Now we can render this component in our provider’s render function.

Rendering the Provider

At this point, we’re almost finished with the infrastructure. There’s just one last thing to do, which is to render the provider within our app. I’m going to place the provider at the root of the entire app so that all children have access to the snackbar.

Opening the Snackbar from Child Components

Now, ButtonA and ButtonB can render their UI and trigger in-app messages without needing to directly receive props from the root of the app! 🤙

Summary

In summary, here’s what happening.

First, we created a context provider component which manages the global state for our snackbar. We then created a component that renders the snackbar’s UI based on the state of the provider. This component subscribes to the provider state in its render function via a context consumer. Finally, we rendered two buttons that update the state of the context provider with the openSnackbar function, which was passed to them via a context consumer. This results in the changes propagating down to the snackbar component, triggering a re-render.

Material UI provides a number of other snackbar features I did not implement with this example, such as action buttons and color customization. For the sake of simplicity I didn’t add the ability to customize those features. Adding that logic yourself would be a great next step if you’re really looking to learn the Context API!

Thank you so much for taking the time to improve yourself. If you found this article useful in any way, I will always accept a clap or two. While you’re at it, take a few seconds and follow me for more great content:

Twitter: @ReisnerShawn

dev.to: @sreisner

Instagram: @shawn.webdev

Happy coding!