In Part 1 of this series, we explored the Outlet Pattern — a technique to render components into specific areas of the DOM regardless of where they are declared in the React tree. In this article, we’ll dive into a real-world implementation of this pattern, using a Bulk Actions Bar component as a practical example.
The Scenario
Imagine you’re working on a Design System where a Bulk Actions Bar should appear anchored to a specific layout area (e.g., below a table header) when items are selected. The challenge? The component triggering the bar and the layout placement for the bar are in entirely different parts of the React tree.
This is where the Outlet Pattern becomes invaluable.
Key Components of the Pattern
1. Outlet Placeholder — BulkActionsBarOutlet
This component defines the exact DOM location where the Bulk Actions Bar should render.
export const BulkActionsBarOutlet = () => {
const { bindRef, portalRendered } = useBulkActionsBarContext()
if (!portalRendered) return null
return (
<div data-component="outlet" ref={bindRef} />
)
}
2. Content Component — BulkActionsBar
The Bulk Actions Bar component is rendered outside the layout flow but visually placed inside the Outlet.
if (refBound && portalRef.current) {
return createPortal(wrappedToolbar, portalRef.current)
}
return wrappedToolbar
3. Context Bridge — useBulkActionsBarContext
A context manages the state and references needed for both Outlet and BulkActionsBar to communicate seamlessly.
Why This Pattern Works
- Layout Agnosticism: The Bulk Actions Bar can be declared anywhere, but still rendered in the correct visual location.
- No Deep Prop Drilling: Components don’t need to pass down placement-related props through multiple layers.
- Portal Safety: Gracefully degrades to inline rendering if the Outlet isn’t ready.
Visual Flow
- Layout renders the Outlet Placeholder.
- The Outlet binds its ref to the context.
- The Bulk Actions Bar checks if the Outlet is ready.
- When ready, it uses
createPortal
to render into the Outlet’s DOM node.
Conclusion
The Outlet Pattern is a powerful architectural tool for decoupling component logic from layout structure. In real-world UI components, such as a Bulk Actions Bar, it provides a clean, scalable solution to complex rendering needs without sacrificing declarative React patterns.
In the next part of this series, we’ll explore how to scale this approach to handle multiple named outlets in a design system context.
Top comments (0)