Modals are a useful tool for displaying information on top of your application, and are often used for notifications, alerts, or standalone dialogs such as registration or login forms. Before building a custom modal, it's a good idea to check if there are any pre-existing solutions that meet your needs (Reach UI's Dialog and react-modal are both popular options). If you don't find a suitable solution, let's explore creating a bespoke modal component in React.
To get started, we'll create a basic modal that appears and disappears based on some local state in our React app. The process is simple: when a button in the root of the app is clicked, the modal will appear. Then, when the button inside the modal is clicked, the modal will close. Let's start building!
If you want to trigger the modal from a nested component rather than just from within
This works for a single level of nesting, but it probably won’t scale very well. We could keep passing the callback down through the components, but that could get a bit tedious and create a lot of extra code that's tough to manage. Enter React Context.
Context allows you to store and access a value anywhere in your React app. You can use a Provider to store the value and a Consumer to access it, and the Consumer will search up the component tree for the first Provider that matches its context. This is useful when you want to trigger the modal from a nested component, rather than just from the top-level App component. You can use the
Let’s wrap the previous example with a Provider, set the
We now have a modal that can be opened from anywhere in our app, but it can only display static content for now. If we want it to render dynamic content, we'll need to refactor it to accept children. Plus, since React's data flow only goes one way, we'll need to find a good way to pass data from a nested component back up to the modal at the root level.
My former colleague, Jenna Smith, a highly skilled front-end developer, suggested using React Portal as a solution. Portal's are designed to pass children to a DOM node outside the hierarchy of the parent component, which is perfect for our needs. To use a portal, we'll need to provide two arguments: a React element (for our dynamic content) and a DOM element to inject the content into (the modal's container). This should allow us to effectively pass the data from the nested component to the modal at the root level.
As demonstrated in the sandbox, Jenna created two functional components to provide dynamic content for the modal. The
With this approach, the