Skip to main content

๐Ÿ“˜ Component Composition in React โ€” Complete Theory Guide


1. Introduction

๐Ÿ”น What is Component Composition?

Component composition is a pattern in React where you build complex UIs by combining smaller, reusable components together. Instead of inheritance, React promotes:
๐Ÿ‘‰ โ€œBuild components using other componentsโ€
function Layout({ children }) {
  return <div className="layout">{children}</div>;
}

function App() {
  return (
    <Layout>
      <h1>Hello</h1>
      <p>Welcome</p>
    </Layout>
  );
}
Here, Layout is composed with child elements.

๐Ÿ”น Why is it Important in React?

  • Encourages reusability
  • Improves maintainability
  • Promotes separation of concerns
  • Aligns with Reactโ€™s declarative model
React is fundamentally built around composition rather than inheritance.

๐Ÿ”น When & Why We Use It

Use component composition when:
  • Building layouts (headers, sidebars, cards)
  • Creating reusable UI patterns
  • Sharing behavior without inheritance
  • Avoiding prop drilling complexity
  • Designing flexible APIs for components

2. Concepts / Internal Workings


๐Ÿ”น 2.1 Composition vs Inheritance

React avoids inheritance because:
  • It creates tight coupling
  • Harder to scale and refactor
Instead, React uses:
<ComponentA>
  <ComponentB />
</ComponentA>

๐Ÿ”น 2.2 The children Prop

At the core of composition is children.
function Card({ children }) {
  return <div className="card">{children}</div>;
}
Usage:
<Card>
  <h2>Title</h2>
  <p>Description</p>
</Card>
๐Ÿ‘‰ Internally:
  • React passes everything inside <Card> as props.children
  • It can be:
    • JSX
    • Arrays
    • Functions
    • Strings

๐Ÿ”น 2.3 Containment Pattern

Used when components act as containers.
function Modal({ children }) {
  return <div className="modal">{children}</div>;
}

๐Ÿ”น 2.4 Specialization Pattern

Creating specific components using generic ones.
function Button({ children }) {
  return <button>{children}</button>;
}

function PrimaryButton() {
  return <Button>Primary</Button>;
}

๐Ÿ”น 2.5 Multiple Slots (Advanced Composition)

Sometimes we need multiple โ€œholesโ€:
function Layout({ header, footer, children }) {
  return (
    <>
      <header>{header}</header>
      <main>{children}</main>
      <footer>{footer}</footer>
    </>
  );
}
Usage:
<Layout
  header={<h1>Header</h1>}
  footer={<p>Footer</p>}
>
  <p>Content</p>
</Layout>

๐Ÿ”น 2.6 Function as Children (Render Props)

A powerful composition pattern:
function DataFetcher({ children }) {
  const data = { name: "John" };
  return children(data);
}

<DataFetcher>
  {(data) => <p>{data.name}</p>}
</DataFetcher>

๐Ÿ”น 2.7 Compound Components Pattern

Components work together as a group:
function Tabs({ children }) {
  return <div>{children}</div>;
}

Tabs.Tab = function Tab({ children }) {
  return <button>{children}</button>;
};

<Tabs>
  <Tabs.Tab>Tab 1</Tabs.Tab>
  <Tabs.Tab>Tab 2</Tabs.Tab>
</Tabs>

๐Ÿ”น 2.8 How It Works Internally in React

  • JSX is transformed into React elements (objects)
  • children becomes part of props
  • During reconciliation:
    • React builds a component tree
    • Each composed component becomes a node
  • React efficiently updates only changed nodes
๐Ÿ‘‰ Composition does NOT create deep inheritance chains โ€” just nested trees.

๐Ÿ”น 2.9 Relationship with Other React Features

โœ” Props

  • Composition heavily relies on props (especially children)

โœ” State

  • State can be lifted or shared across composed components

โœ” Context API

  • Helps avoid prop drilling in deeply composed trees

โœ” Hooks

  • Composition + hooks = reusable logic

3. Syntax & Examples


๐Ÿ”น 3.1 Basic Composition

function Wrapper({ children }) {
  return <div className="wrapper">{children}</div>;
}

function App() {
  return (
    <Wrapper>
      <h1>Hello</h1>
    </Wrapper>
  );
}

๐Ÿ”น 3.2 Reusable Card Component

function Card({ title, children }) {
  return (
    <div className="card">
      <h2>{title}</h2>
      {children}
    </div>
  );
}

<Card title="User">
  <p>Name: John</p>
</Card>

๐Ÿ”น 3.3 Layout Composition

function PageLayout({ sidebar, content }) {
  return (
    <div className="layout">
      <aside>{sidebar}</aside>
      <main>{content}</main>
    </div>
  );
}

<PageLayout
  sidebar={<p>Menu</p>}
  content={<p>Main Content</p>}
/>

๐Ÿ”น 3.4 Wrapper for Styling

function Box({ children }) {
  return <div style={{ padding: "10px" }}>{children}</div>;
}

๐Ÿ”น 3.5 Render Props Example

function Toggle({ children }) {
  const [on, setOn] = React.useState(false);
  return children(on, () => setOn(!on));
}

<Toggle>
  {(on, toggle) => (
    <button onClick={toggle}>
      {on ? "ON" : "OFF"}
    </button>
  )}
</Toggle>

๐Ÿ”น 3.6 Compound Components Example

function Accordion({ children }) {
  return <div>{children}</div>;
}

Accordion.Item = function ({ title, children }) {
  return (
    <div>
      <h3>{title}</h3>
      <div>{children}</div>
    </div>
  );
};

<Accordion>
  <Accordion.Item title="Q1">Answer</Accordion.Item>
</Accordion>

4. Edge Cases / Common Mistakes


โš ๏ธ 4.1 Forgetting to Render children

function Box({ children }) {
  return <div></div>; // โŒ children ignored
}
๐Ÿ‘‰ Fix:
return <div>{children}</div>;

โš ๏ธ 4.2 Over-Composition

Too many layers:
<A>
  <B>
    <C>
      <D />
    </C>
  </B>
</A>
โŒ Leads to:
  • Hard debugging
  • Poor readability

โš ๏ธ 4.3 Prop Drilling Instead of Composition

<Parent data={data}>
  <Child data={data}>
๐Ÿ‘‰ Instead:
  • Use composition or context

โš ๏ธ 4.4 Misusing Render Props

<Data>{data}</Data> // โŒ not a function
๐Ÿ‘‰ Should be:
<Data>{(data) => <div>{data}</div>}</Data>

โš ๏ธ 4.5 Breaking Encapsulation

Passing too much control:
<Component internalStateSetter={setState} />
โŒ Exposes internals

โš ๏ธ 4.6 Key Issues in Composed Lists

{items.map(item => (
  <Card>{item.name}</Card> // โŒ missing key
))}

5. Best Practices


โœ… 5.1 Prefer Composition Over Inheritance

  • Always favor composition-first design

โœ… 5.2 Keep Components Small & Focused

Each component should:
  • Do one thing well
  • Be easily composable

โœ… 5.3 Use Clear Component APIs

Bad:
<Component data1 data2 data3 />
Better:
<Layout header={...} footer={...} />

โœ… 5.4 Avoid Deep Nesting

Flatten when possible:
<Layout>
  <Header />
  <Content />
</Layout>

โœ… 5.5 Combine Composition with Hooks

function useToggle() {
  const [on, setOn] = useState(false);
  return { on, toggle: () => setOn(!on) };
}

โœ… 5.6 Memoization for Performance

Use:
  • React.memo
  • useMemo
  • useCallback
When:
  • Components are deeply composed
  • Props rarely change

โœ… 5.7 Use Compound Components for Complex UI

Ideal for:
  • Tabs
  • Accordions
  • Dropdowns

โœ… 5.8 Use Context to Avoid Prop Drilling

const ThemeContext = React.createContext();

โœ… 5.9 Keep Composition Predictable

  • Avoid hidden side effects
  • Keep data flow clear

๐Ÿ”š Summary

Component composition is the core philosophy of React:
  • Build small โ†’ Combine โ†’ Scale
  • Prefer flexibility over rigid hierarchies
  • Enables powerful patterns like:
    • Render props
    • Compound components
    • Layout systems

๐Ÿ“˜ Advanced Interview Questions โ€” Component Composition (React)


1. What problem does component composition solve that inheritance cannot in React?

โœ… Strong Answer

Composition solves flexibility and decoupling problems that inheritance introduces.
  • Inheritance creates tight coupling between parent-child classes
  • Leads to rigid hierarchies and difficult refactoring
  • React instead uses tree-based composition
๐Ÿ‘‰ With composition:
<Layout>
  <Sidebar />
  <Content />
</Layout>
Each component is:
  • Independent
  • Replaceable
  • Reusable

๐Ÿ’ก Why this matters

Reactโ€™s reconciliation works on a tree of elements, not class hierarchies. Composition maps naturally to this model.

๐Ÿ” Alternative

  • Inheritance โ†’ rigid, static
  • Composition โ†’ dynamic, runtime flexibility

2. How does React internally handle children during reconciliation?

โœ… Strong Answer

  • children is just a prop
  • During JSX transformation:
<Card>
  <p>Hello</p>
</Card>
becomes:
React.createElement(Card, null, React.createElement('p', null, 'Hello'));
๐Ÿ‘‰ Internally:
  • children is stored inside props.children
  • React builds a fiber tree
  • Each child becomes a fiber node

๐Ÿ’ก Key Insight

React does not treat children specially after creation โ€” theyโ€™re just part of the props tree.

โš ๏ธ Pitfall

If children change structure:
  • React diffing depends on keys + order
  • Can cause unnecessary re-renders

3. Why is composition preferred over prop drilling for deep component trees?

โœ… Strong Answer

Prop drilling creates:
  • Tight coupling across layers
  • Hard-to-maintain APIs
  • Increased re-render surface
<Parent data={data}>
  <Child data={data}>
    <GrandChild data={data} />
  </Child>
</Parent>
๐Ÿ‘‰ With composition:
<Parent>
  <GrandChild data={data} />
</Parent>

๐Ÿ’ก Why it works

  • Data stays closer to where itโ€™s needed
  • Intermediate components become agnostic wrappers

๐Ÿ” Alternative

  • Context API for global/shared state
  • Composition for structural flexibility

4. What are the trade-offs between children-based composition and explicit props (slots)?

โœ… Strong Answer

Option 1: children

<Card>
  <Header />
  <Body />
</Card>
โœ” Flexible โŒ Implicit structure (harder to enforce)

Option 2: Named slots

<Card header={<Header />} body={<Body />} />
โœ” Explicit โœ” Easier validation โŒ Slightly verbose

๐Ÿ’ก Trade-off Summary

ApproachFlexibilityReadabilityControl
childrenHighMediumLow
slotsMediumHighHigh
๐Ÿ‘‰ Senior engineers choose based on:
  • API clarity
  • Design constraints

5. Explain the Compound Component pattern and its internal coordination mechanism.

โœ… Strong Answer

Compound components share implicit state via context.
const TabsContext = React.createContext();

function Tabs({ children }) {
  const [active, setActive] = useState(0);

  return (
    <TabsContext.Provider value={{ active, setActive }}>
      {children}
    </TabsContext.Provider>
  );
}
Child components consume it:
function Tab({ index, children }) {
  const { active, setActive } = useContext(TabsContext);

  return (
    <button onClick={() => setActive(index)}>
      {children}
    </button>
  );
}

๐Ÿ’ก Why this works

  • Avoids prop drilling
  • Keeps API clean:
<Tabs>
  <Tab index={0}>Tab 1</Tab>
</Tabs>

โš ๏ธ Trade-off

  • Hidden coupling via context
  • Harder to debug than explicit props

6. When would you avoid using composition and prefer a custom hook instead?

โœ… Strong Answer

Use hooks when sharing logic, not UI. โŒ Composition misuse:
<Toggle>
  {(on) => <Component on={on} />}
</Toggle>
โœ” Better:
const { on, toggle } = useToggle();

๐Ÿ’ก Rule

  • Composition โ†’ UI structure
  • Hooks โ†’ logic reuse

7. What are the performance implications of deeply composed component trees?

โœ… Strong Answer

Deep composition can cause:
  • More fiber nodes
  • Increased reconciliation work
  • Prop changes cascading downward

Example

<A>
  <B>
    <C>
      <D />
    </C>
  </B>
</A>

๐Ÿ’ก Optimization

  • React.memo
  • Avoid unnecessary re-renders
  • Stable props with useCallback

โš ๏ธ Insight

Depth alone isnโ€™t bad โ€” unstable props are the real issue

8. How can composition lead to unnecessary re-renders, and how do you prevent it?

โœ… Strong Answer

Problem:
<Wrapper>
  <Child data={{ value: 1 }} />
</Wrapper>
New object every render โ†’ re-render

Fix:

const data = useMemo(() => ({ value: 1 }), []);
Or:
const Child = React.memo(...)

๐Ÿ’ก Core Idea

Composition amplifies prop instability across tree levels.

9. What is the difference between render props and component composition?

โœ… Strong Answer

Render Props

<Data>
  {(data) => <UI data={data} />}
</Data>
  • Dynamic rendering
  • Logic-driven composition

Composition

<Data>
  <UI />
</Data>
  • Static structure

๐Ÿ’ก Trade-off

PatternFlexibilityComplexity
CompositionMediumLow
Render PropsHighHigher

10. How do you enforce constraints in a highly composable API?

โœ… Strong Answer

Problem:
<Card>
  <RandomComponent />
</Card>
No guarantees of structure.

Solutions:

  1. Runtime validation:
React.Children.forEach(children, child => {
  if (child.type !== AllowedComponent) {
    throw new Error("Invalid child");
  }
});
  1. TypeScript constraints
  2. Compound pattern enforcement

๐Ÿ’ก Trade-off

  • Flexibility vs Safety

11. Why can overusing composition hurt readability?

โœ… Strong Answer

Excess nesting:
<A>
  <B>
    <C>
      <D />
    </C>
  </B>
</A>

Issues:

  • Hard tracing data flow
  • Debug complexity
  • Reduced clarity

๐Ÿ’ก Fix

  • Flatten structure
  • Extract meaningful components

12. How does composition interact with Context API?

โœ… Strong Answer

Context complements composition:
  • Composition defines structure
  • Context provides data access
<ThemeProvider>
  <Layout>
    <Button />
  </Layout>
</ThemeProvider>

๐Ÿ’ก Insight

Without context:
  • Deep composition โ†’ prop drilling
With context:
  • Decoupled data access

13. What are โ€œcontrolled vs uncontrolledโ€ composition patterns?

โœ… Strong Answer

Controlled:

<Tabs active={active} onChange={setActive} />
Parent controls state

Uncontrolled:

<Tabs defaultActive={0} />
Component manages state

๐Ÿ’ก Trade-off

TypeControlComplexity
ControlledHighHigher
UncontrolledLowSimpler

14. How do keys affect composed components?

โœ… Strong Answer

Keys affect:
  • Identity
  • Reconciliation
{items.map(item => (
  <Card key={item.id} />
))}

โš ๏ธ Pitfall

Wrong keys:
key={index}
โ†’ causes:
  • State bugs
  • UI mismatches

15. How would you design a flexible layout system using composition?

โœ… Strong Answer

<Layout>
  <Layout.Header />
  <Layout.Sidebar />
  <Layout.Content />
</Layout>
Internally:
  • Uses context for layout coordination
  • Uses slots for flexibility

๐Ÿ’ก Why this design

  • Declarative API
  • Clear structure
  • Scalable

16. When does composition break encapsulation?

โœ… Strong Answer

If parent controls too much:
<Component setInternalState={setState} />

Problem:

  • Leaks internal logic
  • Breaks abstraction

๐Ÿ’ก Fix

Expose:
  • Callbacks
  • Controlled APIs

17. How does composition influence testability?

โœ… Strong Answer

โœ” Improves testability:
  • Smaller units
  • Easier mocking
render(<Card><MockChild /></Card>);

โš ๏ธ But:

  • Deep composition โ†’ harder integration tests

18. How do you debug issues in a deeply composed component tree?

โœ… Strong Answer

Approach:
  1. Trace props flow
  2. Use React DevTools (component tree)
  3. Check memoization issues
  4. Inspect re-renders

๐Ÿ’ก Senior Insight

Most bugs come from:
  • Incorrect assumptions about composition boundaries
  • Hidden coupling via context

๐Ÿ”š Final Takeaway

Senior-level understanding of composition means:
  • Knowing when NOT to use it
  • Balancing flexibility vs control
  • Understanding how React internally processes trees
  • Designing clean, scalable APIs

๐Ÿ“˜ Advanced MCQs โ€” Component Composition in React (Senior Level)


1. What will be rendered in this composition scenario?

function Wrapper({ children }) {
  return <div>{children}</div>;
}

function App() {
  return (
    <Wrapper>
      {null}
      {false}
      {"Hello"}
    </Wrapper>
  );
}

Options:

A. Nothing renders B. Only "Hello" renders C. null, false, and "Hello" all render D. React throws an error

โœ… Correct Answer: B

โœ” Explanation:

React ignores:
  • null
  • false
  • undefined
Only valid renderable values like strings, numbers, and JSX are rendered. ๐Ÿ‘‰ "Hello" is the only renderable child.

โŒ Why others are wrong:

  • A: Incorrect โ€” "Hello" is rendered
  • C: React does NOT render null or false
  • D: No error occurs

2. What is the key issue in this composition pattern?

function Layout({ children }) {
  return <section>{children}</section>;
}

function App() {
  return (
    <Layout>
      {[<div>A</div>, <div>B</div>]}
    </Layout>
  );
}

Options:

A. Invalid JSX syntax B. Missing keys in children array C. children cannot be arrays D. Layout must use React.Children.map

โœ… Correct Answer: B

โœ” Explanation:

When rendering arrays:
[<div>A</div>, <div>B</div>]
React requires keys for stable reconciliation.

โŒ Why others are wrong:

  • A: Syntax is valid
  • C: Arrays are allowed
  • D: Not required, just optional utility

3. What happens when children change order without keys?

<>
  <Item name="A" />
  <Item name="B" />
</>
โ†’ becomes:
<>
  <Item name="B" />
  <Item name="A" />
</>

Options:

A. React re-renders both correctly B. React swaps DOM nodes efficiently C. State may get mixed between components D. React throws warning and stops rendering

โœ… Correct Answer: C

โœ” Explanation:

Without keys:
  • React uses index-based reconciliation
  • Components may retain wrong state
๐Ÿ‘‰ This leads to state leakage bugs

โŒ Why others are wrong:

  • A: Not guaranteed correct
  • B: Incorrect โ€” React cannot track identity
  • D: Warning only, not a crash

4. What is the issue with this composition?

function Card({ children }) {
  return <div>{children}</div>;
}

<Card>
  <Header />
  <Footer />
</Card>

Options:

A. Nothing is wrong B. Order of children is not guaranteed C. Card cannot accept multiple children D. Header/Footer must be passed as props

โœ… Correct Answer: A

โœ” Explanation:

React preserves:
  • Order
  • Structure of children
This is a valid and common pattern.

โŒ Why others are wrong:

  • B: Order is preserved
  • C: Multiple children allowed
  • D: Not required

5. What is the subtle bug here?

function Wrapper({ children }) {
  return children;
}

Options:

A. Wrapper must return a div B. children must be cloned C. Multiple children will cause an error D. Nothing is wrong

โœ… Correct Answer: D

โœ” Explanation:

React allows returning:
  • A single child
  • Multiple children (as array)
No wrapper needed.

โŒ Why others are wrong:

  • A: Not required (Fragments exist)
  • B: Cloning is optional
  • C: Arrays are valid

6. What is problematic in this pattern?

function Parent({ children }) {
  return React.Children.only(children);
}
Usage:
<Parent>
  <Child1 />
  <Child2 />
</Parent>

Options:

A. Only first child renders B. Runtime error C. Both children render D. Warning only

โœ… Correct Answer: B

โœ” Explanation:

React.Children.only expects exactly one child Multiple children โ†’ throws error

โŒ Why others are wrong:

  • A: It does not silently ignore
  • C: Not allowed
  • D: It throws, not warns

7. What happens in this render prop misuse?

function Data({ children }) {
  return children("data");
}

<Data>
  <div />
</Data>

Options:

A. <div /> renders normally B. children is ignored C. Runtime error D. โ€œdataโ€ is rendered

โœ… Correct Answer: C

โœ” Explanation:

children is expected to be a function, but itโ€™s a React element. Calling it:
children("data")
โ†’ TypeError

โŒ Why others are wrong:

  • A: Incorrect type
  • B: It is executed, not ignored
  • D: Function never runs

8. What is the issue with this composition?

function Modal({ children }) {
  return <div>{children}</div>;
}

<Modal>
  {() => <p>Hello</p>}
</Modal>

Options:

A. Function will render automatically B. Nothing renders C. React throws error D. Function is converted to string

โœ… Correct Answer: B

โœ” Explanation:

React does NOT execute functions passed as children unless explicitly called.
{children()} // required

โŒ Why others are wrong:

  • A: No automatic execution
  • C: No error
  • D: Functions are ignored, not stringified

9. Why is this composition inefficient?

<Wrapper>
  <Child config={{ a: 1 }} />
</Wrapper>

Options:

A. config is invalid B. Wrapper causes re-render C. New object each render breaks memoization D. children cannot accept objects

โœ… Correct Answer: C

โœ” Explanation:

Every render creates new object โ†’ breaks React.memo

โŒ Why others are wrong:

  • A: Valid object
  • B: Not necessarily
  • D: Objects allowed

10. What is the main risk of this compound component pattern?

<Tabs>
  <Tab />
</Tabs>
(with internal context)

Options:

A. Performance issues B. Hidden dependency on parent context C. Cannot scale D. JSX limitation

โœ… Correct Answer: B

โœ” Explanation:

Compound components rely on context โ†’ implicit coupling ๐Ÿ‘‰ <Tab> must be inside <Tabs>

โŒ Why others are wrong:

  • A: Not inherently slow
  • C: It scales well
  • D: No JSX issue

11. What happens if context is missing?

<Tab />
(outside <Tabs>)

Options:

A. Works normally B. Uses default state C. Likely runtime error D. React auto-wraps

โœ… Correct Answer: C

โœ” Explanation:

useContext returns undefined โ†’ accessing properties causes error

โŒ Why others are wrong:

  • A: No context โ†’ broken
  • B: Only if default defined
  • D: React does not auto-wrap

12. What is the issue here?

function Card({ children }) {
  return <div>{children}</div>;
}

<Card children={<p>Hello</p>} />

Options:

A. Invalid syntax B. children prop is overridden C. children cannot be passed explicitly D. Nothing is wrong

โœ… Correct Answer: D

โœ” Explanation:

children is just a prop โ†’ can be passed explicitly

โŒ Why others are wrong:

  • A: Valid
  • B: No override issue
  • C: Allowed

13. What is the risk in this pattern?

function Wrapper({ children }) {
  return React.cloneElement(children, { extra: true });
}

Options:

A. children cannot be cloned B. Only works with one child C. Breaks React rules D. Causes memory leak

โœ… Correct Answer: B

โœ” Explanation:

cloneElement requires a single React element Multiple children โ†’ error

โŒ Why others are wrong:

  • A: It can be cloned
  • C: Valid API
  • D: No leak

14. What is the issue with deep composition and context?

Options:

A. Context cannot pass deeply B. All components re-render on context change C. Context breaks composition D. Context cannot be nested

โœ… Correct Answer: B

โœ” Explanation:

Context updates โ†’ all consumers re-render ๐Ÿ‘‰ Performance concern in large trees

โŒ Why others are wrong:

  • A: It can pass deeply
  • C: They complement each other
  • D: Nesting allowed

15. Why might this API design be problematic?

<Component>
  <Header />
  <Random />
</Component>

Options:

A. JSX invalid B. No control over allowed children C. children must be array D. React disallows mixed types

โœ… Correct Answer: B

โœ” Explanation:

No constraints โ†’ unpredictable structure ๐Ÿ‘‰ Hard to enforce design rules

โŒ Why others are wrong:

  • A: Valid
  • C: Not required
  • D: Allowed

16. What happens when returning arrays from children?

function Wrapper({ children }) {
  return children;
}

Options:

A. Error B. Works if keys exist C. Only first child renders D. Array is flattened automatically

โœ… Correct Answer: B

โœ” Explanation:

React supports arrays, but keys are required for stability.

โŒ Why others are wrong:

  • A: No error
  • C: All children render
  • D: Not โ€œflattenedโ€ automatically

๐Ÿ”š Final Insight

These questions test whether you understand:
  • Composition โ‰  just children
  • It deeply affects:
    • Reconciliation
    • Performance
    • API design
    • Debugging complexity

๐Ÿ“˜ Component Composition โ€” Advanced Coding Problems (React)

These problems simulate real-world UI architecture and design challenges using component composition.

๐Ÿงฉ 1. Flexible Layout System (Slots-Based)

๐Ÿง  Problem

Build a Layout component that supports:
  • Header
  • Sidebar
  • Content
  • Footer
Using composition (not props drilling).

โš™๏ธ Constraints

  • Must allow optional sections
  • Order should not matter
  • Clean API

โœ… Expected Usage

<Layout>
  <Layout.Header>Header</Layout.Header>
  <Layout.Sidebar>Sidebar</Layout.Sidebar>
  <Layout.Content>Main</Layout.Content>
</Layout>

โš ๏ธ Edge Cases

  • Missing sections
  • Multiple headers
  • Invalid children

๐Ÿ’ก Solution (Step-by-step)

  1. Use context to register slots
  2. Identify child types via type
  3. Render in fixed layout positions
const LayoutContext = React.createContext();

function Layout({ children }) {
  const slots = {};

  React.Children.forEach(children, child => {
    slots[child.type.name] = child;
  });

  return (
    <div>
      {slots.Header}
      {slots.Sidebar}
      {slots.Content}
      {slots.Footer}
    </div>
  );
}

๐Ÿงฉ 2. Modal with Controlled & Uncontrolled Modes

๐Ÿง  Problem

Create a Modal that supports:
  • Controlled (isOpen)
  • Uncontrolled (defaultOpen)

โš™๏ธ Constraints

  • Must support both modes cleanly
  • Avoid duplicate state logic

โœ… Expected Behavior

  • Parent can control open state
  • Internal state fallback if not provided

๐Ÿ’ก Solution

function Modal({ isOpen, defaultOpen, children }) {
  const [internal, setInternal] = React.useState(defaultOpen);

  const open = isOpen !== undefined ? isOpen : internal;

  return open ? <div>{children}</div> : null;
}

๐Ÿงฉ 3. Accordion (Compound Components)

๐Ÿง  Problem

Build an accordion where items manage open/close via shared state.

โš™๏ธ Constraints

  • Only one item open at a time
  • Clean composition API

โœ… Expected Usage

<Accordion>
  <Accordion.Item title="Q1">A1</Accordion.Item>
</Accordion>

๐Ÿ’ก Solution

  • Use context for active index
  • Each item reads & updates it

๐Ÿงฉ 4. Tabs with Dynamic Registration

๐Ÿง  Problem

Tabs should:
  • Auto-register children
  • Support dynamic addition/removal

โš ๏ธ Edge Cases

  • Tabs added after mount
  • Missing indices

๐Ÿ’ก Solution Insight

  • Use React.Children.map
  • Use index-based tracking + keys

๐Ÿงฉ 5. Form Builder with Composition

๐Ÿง  Problem

Create a Form component where:
  • Inputs register themselves
  • Form collects values

โœ… Usage

<Form onSubmit={...}>
  <Form.Input name="email" />
  <Form.Input name="password" />
</Form>

๐Ÿ’ก Solution

  • Context for form state
  • Inputs update shared store

๐Ÿงฉ 6. Permission-Based Rendering Wrapper

๐Ÿง  Problem

Render children only if user has permission.

โš™๏ธ Constraints

  • Should support multiple permissions
  • Nested composition

๐Ÿ’ก Solution

function Permission({ allow, children }) {
  const user = useUser();

  return allow.includes(user.role) ? children : null;
}

๐Ÿงฉ 7. Data Fetcher (Render Props vs Composition)

๐Ÿง  Problem

Support both:
<Data>{(data) => ...}</Data>
AND
<Data>
  <Child />
</Data>

โš ๏ธ Edge Case

  • Detect if child is function

๐Ÿ’ก Solution

return typeof children === "function"
  ? children(data)
  : children;

๐Ÿงฉ 8. Card with Strict Child Validation

๐Ÿง  Problem

Card should only allow:
  • Card.Header
  • Card.Body

โš ๏ธ Edge Cases

  • Invalid children
  • Multiple headers

๐Ÿ’ก Solution

React.Children.forEach(children, child => {
  if (![Header, Body].includes(child.type)) {
    throw new Error("Invalid child");
  }
});

๐Ÿงฉ 9. List Virtualization Wrapper

๐Ÿง  Problem

Wrap large lists while preserving composition.

โš™๏ธ Constraints

  • Only render visible items
  • Accept child renderer

๐Ÿ’ก Solution

  • Use render function
  • Combine with windowing logic

๐Ÿงฉ 10. Theme Provider with Composition

๐Ÿง  Problem

Provide theme to deeply nested components.

๐Ÿ’ก Solution

const ThemeContext = React.createContext();

<ThemeContext.Provider value="dark">
  <Layout />
</ThemeContext.Provider>

๐Ÿงฉ 11. Tooltip Wrapper (Composition Control)

๐Ÿง  Problem

Wrap any element with tooltip behavior.

โš ๏ธ Edge Case

  • Child must accept props

๐Ÿ’ก Solution

React.cloneElement(children, {
  onMouseEnter: showTooltip
});

๐Ÿงฉ 12. Error Boundary Wrapper

๐Ÿง  Problem

Catch errors in composed children.

๐Ÿ’ก Solution

  • Use class component
  • Wrap children

๐Ÿงฉ 13. Multi-Step Form Wizard

๐Ÿง  Problem

Steps defined via composition:
<Wizard>
  <Step />
  <Step />
</Wizard>

๐Ÿ’ก Solution

  • Track active step via context
  • Render one step at a time

๐Ÿงฉ 14. Portal-Based Modal System

๐Ÿง  Problem

Render children outside DOM hierarchy.

๐Ÿ’ก Solution

ReactDOM.createPortal(children, document.body);

๐Ÿงฉ 15. Drag-and-Drop Wrapper

๐Ÿง  Problem

Enable drag behavior for any child.

โš ๏ธ Edge Case

  • Child event conflicts

๐Ÿ’ก Solution

  • Inject handlers via cloning

๐Ÿงฉ 16. Layout Switcher (Responsive Composition)

๐Ÿง  Problem

Switch layout based on screen size.

๐Ÿ’ก Solution

  • Conditional composition
return isMobile ? <MobileLayout /> : <DesktopLayout />;

๐Ÿงฉ 17. Notification System (Stacked Composition)

๐Ÿง  Problem

Allow multiple notifications via composition.

๐Ÿ’ก Solution

  • Context store + dynamic children

๐Ÿงฉ 18. Skeleton Loader Wrapper

๐Ÿง  Problem

Wrap content with loading placeholder.

๐Ÿ’ก Solution

function Skeleton({ loading, children }) {
  return loading ? <Loader /> : children;
}

๐Ÿงฉ 19. Access-Controlled Route Wrapper

๐Ÿง  Problem

Restrict route access via composition.

๐Ÿ’ก Solution

<Route element={
  <Protected>
    <Dashboard />
  </Protected>
} />

๐Ÿงฉ 20. Analytics Wrapper (Cross-Cutting Concern)

๐Ÿง  Problem

Track interactions across children.

๐Ÿ’ก Solution

  • Wrap children
  • Inject tracking props/events

๐Ÿ”š Final Takeaway

These problems test your ability to:
  • Design scalable APIs
  • Balance flexibility vs control
  • Handle real-world constraints
  • Understand composition deeply (not just children)

๐Ÿ“˜ Component Composition โ€” Real-World Debugging Challenges (Senior Code Review)

These are production-grade bugs involving composition, not trivial mistakes.

๐Ÿž 1. Children Not Rendering

โŒ Buggy Code

function Card({ children }) {
  return <div className="card"></div>;
}

๐Ÿ” Whatโ€™s Wrong

children is never rendered.

๐Ÿ’ฅ Why It Happens

In composition, children are just props โ€” React wonโ€™t render them automatically.

โœ… Fix

function Card({ children }) {
  return <div className="card">{children}</div>;
}

โœ… Best Practice

Always explicitly render children in container components.

๐Ÿž 2. Broken Memoization Due to Inline Composition

โŒ Buggy Code

const Child = React.memo(({ config }) => {
  console.log("render");
  return <div>{config.value}</div>;
});

function Parent() {
  return (
    <Child config={{ value: 1 }} />
  );
}

๐Ÿ” Whatโ€™s Wrong

Child re-renders every time.

๐Ÿ’ฅ Why It Happens

New object reference on each render โ†’ breaks React.memo.

โœ… Fix

function Parent() {
  const config = React.useMemo(() => ({ value: 1 }), []);
  return <Child config={config} />;
}

โœ… Best Practice

Stabilize props in composed trees using useMemo.

๐Ÿž 3. State Leakage Due to Missing Keys

โŒ Buggy Code

{items.map((item, index) => (
  <Input key={index} value={item.value} />
))}

๐Ÿ” Whatโ€™s Wrong

Inputs show incorrect values after reordering.

๐Ÿ’ฅ Why It Happens

Index-based keys โ†’ React reuses wrong components.

โœ… Fix

{items.map(item => (
  <Input key={item.id} value={item.value} />
))}

โœ… Best Practice

Never use index as key in dynamic composed lists.

๐Ÿž 4. Render Prop Misuse

โŒ Buggy Code

function Fetcher({ children }) {
  const data = { name: "John" };
  return <div>{children}</div>;
}
Usage:
<Fetcher>
  {(data) => <p>{data.name}</p>}
</Fetcher>

๐Ÿ” Whatโ€™s Wrong

Function never executes.

๐Ÿ’ฅ Why It Happens

React does not auto-call function children.

โœ… Fix

return <div>{children(data)}</div>;

โœ… Best Practice

Detect and handle function-as-children explicitly.

๐Ÿž 5. CloneElement Crash with Multiple Children

โŒ Buggy Code

function Wrapper({ children }) {
  return React.cloneElement(children, { active: true });
}
Usage:
<Wrapper>
  <Button />
  <Button />
</Wrapper>

๐Ÿ” Whatโ€™s Wrong

Runtime error.

๐Ÿ’ฅ Why It Happens

cloneElement expects single React element, not array.

โœ… Fix

return React.Children.map(children, child =>
  React.cloneElement(child, { active: true })
);

โœ… Best Practice

Always handle multiple children via React.Children.map.

๐Ÿž 6. Context Undefined in Compound Component

โŒ Buggy Code

const TabsContext = React.createContext();

function Tab() {
  const { active } = React.useContext(TabsContext);
  return <div>{active}</div>;
}
Usage:
<Tab />

๐Ÿ” Whatโ€™s Wrong

App crashes.

๐Ÿ’ฅ Why It Happens

No provider โ†’ useContext returns undefined.

โœ… Fix

const context = React.useContext(TabsContext);
if (!context) throw new Error("Tab must be inside Tabs");

โœ… Best Practice

Guard compound components against missing providers.

๐Ÿž 7. Hidden Re-render Cascade

โŒ Buggy Code

function Parent() {
  const [count, setCount] = useState(0);

  return (
    <Wrapper>
      <Child />
    </Wrapper>
  );
}

๐Ÿ” Whatโ€™s Wrong

Child re-renders even if it doesnโ€™t use count.

๐Ÿ’ฅ Why It Happens

Parent re-render โ†’ all children re-render.

โœ… Fix

const Child = React.memo(() => { ... });

โœ… Best Practice

Memoize deeply composed children.

๐Ÿž 8. Incorrect Child Type Assumption

โŒ Buggy Code

React.Children.forEach(children, child => {
  console.log(child.props.name);
});

๐Ÿ” Whatโ€™s Wrong

Crashes when child is string/null.

๐Ÿ’ฅ Why It Happens

Children can be:
  • strings
  • null
  • arrays

โœ… Fix

if (React.isValidElement(child)) {
  console.log(child.props.name);
}

โœ… Best Practice

Always validate children before accessing props.

๐Ÿž 9. Function Child Not Called Conditionally

โŒ Buggy Code

return children && children(data);

๐Ÿ” Whatโ€™s Wrong

Crashes if children is not function.

๐Ÿ’ฅ Why It Happens

Assumes children is callable.

โœ… Fix

return typeof children === "function"
  ? children(data)
  : children;

โœ… Best Practice

Support both patterns safely.

๐Ÿž 10. Overwriting Event Handlers

โŒ Buggy Code

React.cloneElement(children, {
  onClick: () => console.log("wrapper")
});

๐Ÿ” Whatโ€™s Wrong

Childโ€™s original onClick lost.

๐Ÿ’ฅ Why It Happens

Props are overwritten.

โœ… Fix

const original = children.props.onClick;

React.cloneElement(children, {
  onClick: (e) => {
    original?.(e);
    console.log("wrapper");
  }
});

โœ… Best Practice

Merge, donโ€™t override props.

๐Ÿž 11. Multiple Slot Collision

โŒ Buggy Code

slots[child.type.name] = child;

๐Ÿ” Whatโ€™s Wrong

Only last child kept.

๐Ÿ’ฅ Why It Happens

Same key overwritten.

โœ… Fix

slots[child.type.name] = [
  ...(slots[child.type.name] || []),
  child
];

โœ… Best Practice

Handle multiple instances safely.

๐Ÿž 12. Stale Closure in Composed Callback

โŒ Buggy Code

function Wrapper({ children }) {
  const [count, setCount] = useState(0);

  return React.cloneElement(children, {
    onClick: () => setCount(count + 1)
  });
}

๐Ÿ” Whatโ€™s Wrong

May use stale count.

๐Ÿ’ฅ Why It Happens

Closure captures old state.

โœ… Fix

onClick: () => setCount(c => c + 1)

โœ… Best Practice

Use functional updates in composed callbacks.

๐Ÿž 13. Fragment Children Misinterpretation

โŒ Buggy Code

React.Children.count(children) === 1

๐Ÿ” Whatโ€™s Wrong

Fails for fragments.

๐Ÿ’ฅ Why It Happens

Fragments wrap multiple children but count as one.

โœ… Fix

React.Children.toArray(children).length

โœ… Best Practice

Normalize children before inspection.

๐Ÿž 14. Conditional Rendering Losing State

โŒ Buggy Code

{show && <Child />}

๐Ÿ” Whatโ€™s Wrong

Child state resets when toggled.

๐Ÿ’ฅ Why It Happens

Component unmounts/remounts.

โœ… Fix

<Child hidden={!show} />

โœ… Best Practice

Avoid unmounting when state must persist.

๐Ÿž 15. Deep Composition Causing Prop Drilling

โŒ Buggy Code

<A data={data}>
  <B data={data}>
    <C data={data} />
  </B>
</A>

๐Ÿ” Whatโ€™s Wrong

Unnecessary prop passing.

๐Ÿ’ฅ Why It Happens

Poor composition design.

โœ… Fix

Use context:
<DataContext.Provider value={data}>
  <C />
</DataContext.Provider>

โœ… Best Practice

Use context for deeply shared data.

๐Ÿž 16. Unstable Child Identity

โŒ Buggy Code

<Wrapper>
  {() => <Child />}
</Wrapper>

๐Ÿ” Whatโ€™s Wrong

New function every render โ†’ re-renders.

๐Ÿ’ฅ Why It Happens

Function identity changes.

โœ… Fix

const renderChild = useCallback(() => <Child />, []);

โœ… Best Practice

Stabilize function props.

๐Ÿž 17. Unexpected Rendering Order

โŒ Buggy Code

React.Children.map(children, child => {
  return condition ? child : null;
});

๐Ÿ” Whatโ€™s Wrong

Keys shift โ†’ order instability.

๐Ÿ’ฅ Why It Happens

Filtering without preserving keys.

โœ… Fix

React.Children.toArray(children).filter(...)

โœ… Best Practice

Normalize + filter safely.

๐Ÿž 18. Infinite Re-render Loop via Composition

โŒ Buggy Code

function Parent() {
  const [state, setState] = useState(0);

  return (
    <Child update={() => setState(state + 1)} />
  );
}

๐Ÿ” Whatโ€™s Wrong

Child triggers update โ†’ infinite loop.

๐Ÿ’ฅ Why It Happens

Unstable callback causes repeated updates.

โœ… Fix

const update = useCallback(() => {
  setState(s => s + 1);
}, []);

โœ… Best Practice

Stabilize callbacks passed through composition.

๐Ÿ”š Final Takeaway

Real-world composition bugs usually come from:
  • โŒ Wrong assumptions about children
  • โŒ Unstable references (objects/functions)
  • โŒ Hidden coupling (context, compound patterns)
  • โŒ Misuse of React utilities (cloneElement, Children)
  • โŒ Reconciliation misunderstandings

๐Ÿ“˜ Component Composition โ€” Real-World Machine Coding Problems (Senior Architect Level)

These problems simulate production-grade frontend architecture challenges where component composition is central.

๐Ÿงฉ 1. Headless Dropdown System (Composable API)

๐Ÿง  Problem

Build a fully accessible dropdown system with:
  • Trigger
  • Menu
  • Items

โœ… Requirements

  • Keyboard navigation (โ†‘ โ†“ Enter Esc)
  • Controlled + uncontrolled modes
  • Custom rendering of items

๐ŸŽฏ UI Behavior

  • Clicking trigger toggles menu
  • Arrow keys navigate items
  • Only one item active

๐Ÿ”„ State/Data Flow

  • Shared via context:
    • isOpen
    • activeIndex
    • selectItem

โš ๏ธ Edge Cases

  • Click outside to close
  • Dynamic items list
  • Nested dropdowns

โšก Performance

  • Avoid re-renders on hover
  • Memoize item list

๐Ÿ— Suggested Architecture

<Dropdown>
  <Dropdown.Trigger />
  <Dropdown.Menu>
    <Dropdown.Item />
  </Dropdown.Menu>
</Dropdown>

๐Ÿ›  Approach

  1. Create context
  2. Register items dynamically
  3. Handle keyboard events globally
  4. Use refs for focus control

๐Ÿงฉ 2. Headless Modal System with Portal

๐Ÿง  Problem

Create a composable modal system supporting:
  • Multiple modals
  • Nested modals
  • Portal rendering

๐ŸŽฏ UI Behavior

  • Modal overlays page
  • Focus trapped inside
  • Escape closes modal

๐Ÿ”„ Data Flow

  • Global modal manager (context/store)

โš ๏ธ Edge Cases

  • Multiple modals stacked
  • Background scroll lock

โšก Performance

  • Avoid re-rendering entire app
  • Use portals for isolation

๐Ÿ— Architecture

<Modal>
  <Modal.Trigger />
  <Modal.Content />
</Modal>

๐Ÿ›  Approach

  1. Use createPortal
  2. Manage modal stack
  3. Trap focus with refs

๐Ÿงฉ 3. Dynamic Form Builder (Schema + Composition)

๐Ÿง  Problem

Build a form system where:
  • Fields self-register
  • Supports validation & dynamic fields

๐ŸŽฏ UI Behavior

  • Real-time validation
  • Dynamic addition/removal of fields

๐Ÿ”„ Data Flow

  • Central form state via context

โš ๏ธ Edge Cases

  • Nested fields
  • Async validation

โšก Performance

  • Avoid re-rendering entire form
  • Field-level subscriptions

๐Ÿ— Architecture

<Form>
  <Form.Field name="email" />
</Form>

๐Ÿ›  Approach

  1. Create field registry
  2. Use context for state
  3. Isolate updates per field

๐Ÿงฉ 4. Compound Tabs with Lazy Rendering

๐Ÿง  Problem

Tabs where inactive panels are not rendered.

โš ๏ธ Edge Cases

  • Preserving state on unmount
  • Dynamic tab addition

โšก Performance

  • Lazy mount panels
  • Memoize tab content

๐Ÿ— Architecture

<Tabs>
  <Tabs.List />
  <Tabs.Panel />
</Tabs>

๐Ÿ›  Approach

  • Track active tab
  • Conditionally render panel

๐Ÿงฉ 5. Notification System (Global + Composable)

๐Ÿง  Problem

Create a toast system with:
  • Stacked notifications
  • Auto-dismiss
  • Custom content

๐Ÿ”„ Data Flow

  • Global context store

โš ๏ธ Edge Cases

  • Rapid fire notifications
  • Duplicate messages

โšก Performance

  • Avoid re-rendering all toasts

๐Ÿ— Architecture

<ToastProvider>
  <App />
</ToastProvider>

๐Ÿ›  Approach

  • Maintain queue
  • Render via portal

๐Ÿงฉ 6. Drag-and-Drop Composable System

๐Ÿง  Problem

Enable drag-drop via composition.

โš ๏ธ Edge Cases

  • Nested draggables
  • Performance on large lists

โšก Performance

  • Avoid full re-renders during drag

๐Ÿ— Architecture

<Draggable>
  <Item />
</Draggable>

๐Ÿ›  Approach

  • Inject props via cloneElement
  • Use refs for DOM tracking

๐Ÿงฉ 7. Virtualized List with Render Composition

๐Ÿง  Problem

Render large datasets efficiently.

โš ๏ธ Edge Cases

  • Dynamic item heights
  • Scroll jumps

โšก Performance

  • Windowing
  • Memoized item renderer

๐Ÿ— Architecture

<VirtualList>
  {(item) => <Row item={item} />}
</VirtualList>

๐Ÿ›  Approach

  • Calculate visible range
  • Render subset

๐Ÿงฉ 8. Multi-Step Wizard

๐Ÿง  Problem

Composable steps with shared state.

โš ๏ธ Edge Cases

  • Skippable steps
  • Async validation

๐Ÿ— Architecture

<Wizard>
  <Step />
</Wizard>

๐Ÿ›  Approach

  • Track current step
  • Share state via context

๐Ÿงฉ 9. Access-Control Wrapper System

๐Ÿง  Problem

Control UI visibility based on roles.

โš ๏ธ Edge Cases

  • Nested permissions
  • Async auth

๐Ÿ— Architecture

<Protected roles={["admin"]}>
  <Dashboard />
</Protected>

๐Ÿ›  Approach

  • Context-based auth
  • Conditional rendering

๐Ÿงฉ 10. Analytics Wrapper

๐Ÿง  Problem

Track user interactions across app.

โš ๏ธ Edge Cases

  • Prevent duplicate tracking
  • Debounce events

๐Ÿ— Architecture

<Track event="click">
  <Button />
</Track>

๐Ÿ›  Approach

  • Inject handlers via cloning
  • Central tracking system

๐Ÿงฉ 11. Layout System with Responsive Composition

๐Ÿง  Problem

Switch layout dynamically.

โš ๏ธ Edge Cases

  • Resize events
  • SSR mismatch

๐Ÿ— Architecture

<ResponsiveLayout />

๐Ÿ›  Approach

  • Media queries + composition switching

๐Ÿงฉ 12. Skeleton Loader Wrapper

๐Ÿง  Problem

Wrap any component with loading state.

โš ๏ธ Edge Cases

  • Partial loading
  • Layout shifts

๐Ÿ›  Approach

  • Conditional rendering + placeholder

๐Ÿงฉ 13. Infinite Scroll Feed

๐Ÿง  Problem

Composable feed with lazy loading.

โš ๏ธ Edge Cases

  • Scroll threshold issues
  • Duplicate fetches

๐Ÿ›  Approach

  • IntersectionObserver
  • State batching

๐Ÿงฉ 14. Global Search Overlay

๐Ÿง  Problem

Search UI accessible anywhere.

โš ๏ธ Edge Cases

  • Keyboard shortcut conflicts
  • Debounce search

๐Ÿ›  Approach

  • Portal + context

๐Ÿงฉ 15. Table System (Headless + Composable)

๐Ÿง  Problem

Customizable table:
  • Columns
  • Sorting
  • Pagination

โš ๏ธ Edge Cases

  • Large datasets
  • Column reordering

๐Ÿ›  Approach

  • Headless logic + UI composition

๐Ÿงฉ 16. Feature Flag Wrapper

๐Ÿง  Problem

Enable/disable features dynamically.

โš ๏ธ Edge Cases

  • Async flags
  • A/B testing

๐Ÿ›  Approach

  • Context-based flags

๐Ÿงฉ 17. Error Boundary System (Composable)

๐Ÿง  Problem

Wrap parts of app for error isolation.

โš ๏ธ Edge Cases

  • Nested boundaries
  • Reset behavior

๐Ÿ›  Approach

  • Class-based error boundaries

๐Ÿงฉ 18. Command Palette (Keyboard Driven UI)

๐Ÿง  Problem

Global command system (like VS Code).

โš ๏ธ Edge Cases

  • Focus management
  • Search ranking

๐Ÿ›  Approach

  • Context + portal + keyboard events

๐Ÿงฉ 19. Timeline/Activity Feed System

๐Ÿง  Problem

Composable event feed with grouping.

โš ๏ธ Edge Cases

  • Time grouping
  • Dynamic updates

๐Ÿ›  Approach

  • Data transformation + composed UI

๐Ÿงฉ 20. Nested Menu System

๐Ÿง  Problem

Multi-level navigation menus.

โš ๏ธ Edge Cases

  • Keyboard navigation
  • Deep nesting

๐Ÿ›  Approach

  • Recursive composition
  • Context for active state

๐Ÿ”š Final Takeaway

These problems test true senior-level skills:
  • Designing composable APIs
  • Managing state across trees
  • Handling performance + edge cases
  • Balancing flexibility vs control

๐Ÿ“˜ FAANG-Level Interview Questions โ€” Component Composition (React)

These questions probe architecture thinking, trade-offs, debugging ability, and performance awareness โ€” not surface knowledge.

1. Design a flexible Modal API using composition. What trade-offs would you consider?

๐Ÿ” Follow-ups

  • How would you support nested modals?
  • How would you prevent misuse of subcomponents?

โœ… Strong Answer

  • Use compound components:
<Modal>
  <Modal.Trigger />
  <Modal.Content />
</Modal>
  • Share state via context
  • Use portal for rendering
  • Add guards for invalid usage

๐Ÿ’ก Trade-offs

  • Flexibility vs API constraints
  • Context coupling vs explicit props

โŒ Weak Answer

โ€œJust pass isOpen prop and render childrenโ€ ๐Ÿ‘‰ Fails because:
  • Ignores composability
  • Doesnโ€™t scale for complex UI

2. When would you prefer render props over composition?

๐Ÿ” Follow-ups

  • What are performance implications?
  • How does it affect readability?

โœ… Strong Answer

  • Use render props when:
    • UI depends on dynamic data/logic
    • Need runtime control
<Data>{(data) => <UI data={data} />}</Data>

๐Ÿ’ก Trade-off

  • More flexible but harder to read/debug

โŒ Weak Answer

โ€œRender props are just another way to pass childrenโ€ ๐Ÿ‘‰ Misses key difference: function execution vs static structure

3. How does React treat children internally, and why does it matter for performance?

๐Ÿ” Follow-ups

  • How does reconciliation use keys?
  • What happens with unstable children?

โœ… Strong Answer

  • children โ†’ part of props
  • Converted into fiber nodes
  • Reconciliation depends on:
    • Keys
    • Order
๐Ÿ‘‰ Unstable children โ†’ unnecessary re-renders

โŒ Weak Answer

โ€œChildren is just JSXโ€ ๐Ÿ‘‰ Too shallow, no understanding of reconciliation

4. You see unnecessary re-renders in a deeply composed tree. How do you debug?

๐Ÿ” Follow-ups

  • What tools would you use?
  • How do you isolate the issue?

โœ… Strong Answer

  1. Use React DevTools (highlight updates)
  2. Check prop identity (objects/functions)
  3. Add React.memo
  4. Profile renders

โŒ Weak Answer

โ€œUse memo everywhereโ€ ๐Ÿ‘‰ Blind optimization without root cause analysis

5. Design a Tabs system using composition. How do you handle state sharing?

๐Ÿ” Follow-ups

  • What if tabs are dynamically added?
  • How do you prevent misuse?

โœ… Strong Answer

  • Compound components + context
  • Track active index
  • Register children dynamically

โŒ Weak Answer

โ€œPass active tab as prop to each Tabโ€ ๐Ÿ‘‰ Leads to prop drilling and poor scalability

6. What are the risks of overusing composition?

๐Ÿ” Follow-ups

  • When does composition hurt readability?
  • How do you balance abstraction?

โœ… Strong Answer

  • Deep nesting โ†’ hard debugging
  • Implicit structure โ†’ unclear APIs
  • Hidden coupling via context

โŒ Weak Answer

โ€œNo downsides, composition is always goodโ€ ๐Ÿ‘‰ Shows lack of real-world experience

7. How do you enforce constraints in a composable API?

๐Ÿ” Follow-ups

  • Compile-time vs runtime validation?

โœ… Strong Answer

  • Use:
    • TypeScript typings
    • Runtime validation (child.type)
    • Controlled compound components

โŒ Weak Answer

โ€œDocument itโ€ ๐Ÿ‘‰ Documentation is not enforcement

8. Compare composition vs custom hooks for reuse.

๐Ÿ” Follow-ups

  • Can they be combined?

โœ… Strong Answer

  • Composition โ†’ UI reuse
  • Hooks โ†’ logic reuse
๐Ÿ‘‰ Best systems combine both

โŒ Weak Answer

โ€œThey are interchangeableโ€ ๐Ÿ‘‰ Incorrect mental model

9. How does composition impact bundle size and performance?

๐Ÿ” Follow-ups

  • Tree-shaking implications?

โœ… Strong Answer

  • More components โ‰  worse performance
  • But:
    • More layers โ†’ more renders
    • Inline functions/objects hurt memoization

โŒ Weak Answer

โ€œMore components always slowerโ€ ๐Ÿ‘‰ Oversimplified and incorrect

10. How would you design a headless UI component system?

๐Ÿ” Follow-ups

  • How do you separate logic from UI?

โœ… Strong Answer

  • Provide logic via hooks/context
  • Let consumers compose UI
<Dropdown>
  <Dropdown.Trigger />
  <Dropdown.Menu />
</Dropdown>

โŒ Weak Answer

โ€œJust style componentsโ€ ๐Ÿ‘‰ Misses headless concept

11. What issues arise with React.cloneElement in composition?

๐Ÿ” Follow-ups

  • Alternatives?

โœ… Strong Answer

  • Only works with single child
  • Overrides props unintentionally
  • Breaks ref forwarding

โŒ Weak Answer

โ€œItโ€™s fine to use everywhereโ€ ๐Ÿ‘‰ Ignores limitations

12. How do keys affect composed components beyond lists?

๐Ÿ” Follow-ups

  • Can keys reset state?

โœ… Strong Answer

  • Keys control identity
  • Changing key โ†’ remount โ†’ state reset

โŒ Weak Answer

โ€œKeys are only for listsโ€ ๐Ÿ‘‰ Incorrect

13. Design a system to avoid prop drilling in deep composition.

๐Ÿ” Follow-ups

  • When NOT to use context?

โœ… Strong Answer

  • Use context for shared data
  • Avoid overusing context (performance issues)

โŒ Weak Answer

โ€œAlways use contextโ€ ๐Ÿ‘‰ Ignores trade-offs

14. What is a subtle bug when using function-as-children?

๐Ÿ” Follow-ups

  • Performance implications?

โœ… Strong Answer

  • Function recreated each render
  • Causes re-renders if not memoized

โŒ Weak Answer

โ€œNo issuesโ€ ๐Ÿ‘‰ Misses real-world impact

15. How do you design a scalable layout system using composition?

๐Ÿ” Follow-ups

  • Slot-based vs children-based?

โœ… Strong Answer

  • Use slots for clarity:
<Layout header={} sidebar={} />
OR compound pattern

โŒ Weak Answer

โ€œJust use divsโ€ ๐Ÿ‘‰ Not architectural thinking

16. How would you debug a broken compound component system?

๐Ÿ” Follow-ups

  • What if context is undefined?

โœ… Strong Answer

  • Check provider presence
  • Validate usage
  • Add error boundaries

โŒ Weak Answer

โ€œCheck console logsโ€ ๐Ÿ‘‰ Too shallow

17. When does composition break encapsulation?

๐Ÿ” Follow-ups

  • How do you fix it?

โœ… Strong Answer

  • Exposing internal state setters
  • Allowing uncontrolled manipulation
๐Ÿ‘‰ Fix via controlled APIs

โŒ Weak Answer

โ€œIt doesnโ€™tโ€ ๐Ÿ‘‰ Incorrect

18. How does composition interact with Suspense and lazy loading?

๐Ÿ” Follow-ups

  • Where do you place boundaries?

โœ… Strong Answer

  • Wrap composed parts with Suspense
  • Lazy load heavy children

โŒ Weak Answer

โ€œSuspense handles everythingโ€ ๐Ÿ‘‰ Oversimplified

19. Design a reusable analytics wrapper using composition.

๐Ÿ” Follow-ups

  • Avoid double tracking?

โœ… Strong Answer

  • Wrap children
  • Inject event handlers carefully
  • Deduplicate events

โŒ Weak Answer

โ€œLog inside componentโ€ ๐Ÿ‘‰ Not reusable/composable

20. What is the hardest part of designing composable systems at scale?

๐Ÿ” Follow-ups

  • How do you measure success?

โœ… Strong Answer

  • Balancing:
    • Flexibility
    • Constraints
    • Performance
  • Avoiding hidden coupling

โŒ Weak Answer

โ€œJust reuse componentsโ€ ๐Ÿ‘‰ Misses system design depth

๐Ÿ”š Final Insight

A strong candidate demonstrates:
  • Deep understanding of React internals
  • Ability to reason about trade-offs
  • Awareness of performance & debugging
  • Skill in designing clean, scalable APIs