- React
- Advanced Component Design Patterns and Error Boundaries
- Slot Pattern & Inversion of Control in UI Architecture
Slot Pattern & Inversion of Control in UI Architecture
The Slot Pattern passes React elements as dedicated props (like header, footer, or sidebar) rather than restricting layout to children, achieving inversion of control, eliminating deep prop drilling, and decoupling container layout from child business logic.
Key Learning Objectives
Implement the Slot pattern using named JSX props (headerSlot, actionSlot).
Explain Inversion of Control (IoC) and how it solves deep prop drilling.
Compare named props slots against the Radix UI `<Slot>` primitive pattern.
Prevent unnecessary re-renders of container layouts by lifting child instantiation to parents.
The Interview Problem & Context
Demonstrate how using named slot props achieves Inversion of Control (IoC) to eliminate prop drilling in a multi-section Card or Dashboard layout.
1import React, { ReactNode } from 'react';23interface DashboardCardProps {4 title: string;5 // Named slots: First-class JSX elements passed as props6 headerActionSlot?: ReactNode;7 contentSlot: ReactNode;8 footerSlot?: ReactNode;9}1011// Container component: Focuses solely on layout and structure12export function DashboardCard({13 title,14 headerActionSlot,15 contentSlot,16 footerSlot,17}: DashboardCardProps) {18 return (19 <div className="dashboard-card border rounded-lg p-4 shadow">20 <header className="flex justify-between items-center mb-4">21 <h3 className="font-bold text-lg">{title}</h3>22 {headerActionSlot && <div className="header-slot">{headerActionSlot}</div>}23 </header>2425 <main className="card-body mb-4">{contentSlot}</main>2627 {footerSlot && <footer className="card-footer border-t pt-2">{footerSlot}</footer>}28 </div>29 );30}3132// Consumer: Controls business logic, handlers, and rendering details33export function AnalyticsWidget() {34 const handleExport = () => console.log('Exporting CSV...');3536 return (37 <DashboardCard38 title="Monthly Revenue"39 headerActionSlot={40 <button onClick={handleExport} className="btn-sm">41 Export42 </button>43 }44 contentSlot={<div className="chart-placeholder">Revenue Chart: $45,000</div>}45 footerSlot={<span>Updated 2 minutes ago</span>}46 />47 );48}
Deep Architectural Explanation
The Power of Inversion of Control (IoC)
Without the Slot pattern, developers fall into the Config Prop Anti-Pattern:
// Anti-pattern: Container must know every possible action and button!
<DashboardCard
title="Monthly Revenue"
showExportButton={true}
onExport={handleExport}
showRefreshButton={true}
onRefresh={handleRefresh}
exportButtonLabel="Download CSV"
/>Every time product requirements change, the container component must be edited, bloated with new props, and re-tested!
With Named Slots:
- Container Decoupling:
<DashboardCard>only manages layout, borders, and margins. It has zero knowledge of export logic. - Inversion of Control: The parent controls what is rendered, what handlers are attached, and what data is consumed.
- Performance Win:
DashboardCarddoes not need to re-render if the child component insidecontentSlotupdates its internal state.
Common Interview Traps & Pitfalls
Creating dozens of boolean flag props (showExport, showIcon) instead of providing an action slot.
Hardcoding child layout assumptions inside the parent container.
Passing component functions instead of rendered JSX elements when static elements suffice.
Senior Interviewer Follow-Up Probes
How does Radix UI use `<Slot>` to merge props and event handlers onto immediate children?
How does the slot pattern compare to Web Components native `<slot>` elements?
How can default fallback content be provided if a slot prop is omitted?
Frequently Asked Interview Questions
How does the Slot pattern provide Inversion of Control?
It shifts responsibility for creating and configuring subcomponents from the container component to the consuming parent, preventing container prop bloat and decoupling business logic.
What is the difference between props.children and named slots?
props.children represents a single default content insertion point. Named slots allow multiple distinct insertion points (e.g., top header, side panel, bottom footer) within a single container layout.
Can you provide default fallback content for a slot?
Yes. In the container component, use default parameters or conditional rendering: {headerSlot ?? <DefaultHeader />}
How does Radix UI Slot component work?
Radix UI Slot renders no DOM node of its own; instead, it clones its immediate child and merges the container props, classes, and event handlers directly onto that child element.
Does passing elements into slots cause unnecessary re-renders?
No. In fact, it often reduces re-renders because the container does not hold state related to the slotted content, keeping component boundaries clean.
