Creating Portals in React with the usePortal Hook
Published: 2024-01-06 18:04:37


React provides a powerful way to build user interfaces, but sometimes you encounter situations where you need to render components outside of the normal React tree. This is where portals come in handy. Portals allow you to render a component outside its parent DOM hierarchy, often useful for scenarios like modals, tooltips, or other overlays.

In this article, we'll explore a custom React hook called `usePortal` that simplifies the process of creating portals in your React applications.

# Introducing `usePortal`

The `usePortal` hook is designed to be a reusable utility that encapsulates the logic for creating and managing portals. Let's dive into the key aspects of this hook.

1. Basic Usage
   The `usePortal` hook takes a configuration object as an argument, including an id for the portal, optional `attributes` for styling, and other customization options. Here's a basic example:

   ```tsx
   import { usePortal } from 'path-to-usePortal';

   const MyComponent = () => {
     const { elRef, id } = usePortal({ id: 'myPortal' });

     // Use elRef in your component as a reference to the portal element
     return (
       <div>
         {/* Your regular React component content */}
         <div ref={elRef}>
           {/* Portal content goes here */}
           This content is rendered outside the component hierarchy!
         </div>
       </div>
     );
   };
   ```

2. Custom Styling
   You can customize the styling of the portal by providing additional options like `className`, `elementClass`, and `attributes`. For example:

   ```tsx
   const MyStyledPortal = () => {
     const { elRef, id } = usePortal({
       id: 'styledPortal',
       className: 'my-custom-styles',
       elementClass: 'portal-content',
       attributes: { zIndex: 100 },
     });

     return (
       <div>
         <div ref={elRef}>Stylish portal content goes here!</div>
       </div>
     );
   };
   ```

3. Dynamically Changing Portals
   The `usePortal` hook is also designed to handle scenarios where the portal configuration changes dynamically. For example, you can update the portal ID, attributes, or other options during the component lifecycle.

   ```tsx
   const DynamicPortal = ({ dynamicId }) => {
     const { elRef, id } = usePortal({ id: dynamicId });
     return (
       <div>
         <div ref={elRef}>Content for the dynamic portal!</div>
       </div>
     );
   };
   ```

# Under the Hood

Now, let's take a peek under the hood to understand how the `usePortal` hook achieves its magic.

- **Portal Element Creation**: The hook utilizes a `MutableRefObject` to keep track of the portal element. If it doesn't exist, it creates a new `div` element.

- **Appending to DOM**: The hook uses the `useEffect` hook to manage the lifecycle of the portal. It checks if the portal root exists and creates it if not. Then, it appends the portal element to the portal root.

- **Cleanup**: The `useEffect` hook also ensures proper cleanup by removing the portal element from the DOM when the component unmounts.

# Conclusion

The `usePortal` hook is a versatile tool for handling portal creation in `React` applications. Whether you're building `modals`, `tooltips`, or any other overlay components, this hook provides a clean and reusable solution. Feel free to customize it to suit your specific use cases.

Happy coding!