DEV Community

Cover image for Container/Presentational Pattern in React
Md Enayetur Rahman
Md Enayetur Rahman

Posted on

Container/Presentational Pattern in React

A deep‑dive based on **“Learning Patterns” by Lydia Hallie & Addy Osmani”

“In React, one way to enforce separation of concerns is by using the Container/Presentational pattern.”


1  Why this pattern exists

Modern UIs juggle two distinct responsibilities: what data to show (application logic) and how to display it (view logic). The Container/Presentational pattern formalises that split:

Layer Responsibility Typical code
Presentational Component Render the UI; accept data via props; stateless (or UI‑only state) Pure function component
Container Component Fetch / transform data; hold state; pass props down Often uses hooks, context, or data‑fetching libs

Separating these layers keeps each file focussed and easier to reason about, test, and reuse. Presentational components remain visually driven, while containers orchestrate data flow.


2  Presentational component example

// DogsImages.js — Presentational
export default function DogsImages({ images }) {
  return (
    <section className="dogs-grid">
      {images.map((src) => (
        <img key={src} src={src} alt="Cute dog" />
      ))}
    </section>
  );
}
Enter fullscreen mode Exit fullscreen mode
  • Receives images via props.
  • No API calls, no business logic. Just transforms data → DOM.
  • Can be reused anywhere images are needed. Presentational components are usually stateless and don’t mutate their props.

3  Container component example

// DogsImagesContainer.js — Container
import { useEffect, useState } from "react";
import DogsImages from "./DogsImages";

export default function DogsImagesContainer() {
  const [images, setImages] = useState([]);

  useEffect(() => {
    fetch("https://dog.ceo/api/breeds/image/random/6")
      .then((r) => r.json())
      .then((data) => setImages(data.message));
  }, []);

  return <DogsImages images={images} />;
}
Enter fullscreen mode Exit fullscreen mode
  • Handles what data to show by fetching from an API, then delegates how to show it to DogsImages.
  • Renders nothing else; no styling of its own—typical of containers.

4  Hooks as a lighter alternative

With the arrival of React Hooks, you can move stateful logic into a custom hook and call it directly from the presentational component—skipping the wrapper layer:

// useDogImages.js
import { useEffect, useState } from "react";
export function useDogImages(count = 6) {
  const [images, setImages] = useState([]);
  useEffect(() => {
    fetch(`https://dog.ceo/api/breeds/image/random/${count}`)
      .then((r) => r.json())
      .then((data) => setImages(data.message));
  }, [count]);
  return images;
}

// DogsImages.js
import { useDogImages } from "./useDogImages";
export default function DogsImages() {
  const images = useDogImages();
  return (
    <section className="dogs-grid">
      {images.map((src) => (
        <img key={src} src={src} alt="Cute dog" />
      ))}
    </section>
  );
}
Enter fullscreen mode Exit fullscreen mode

Hooks “save us the extra layer that was necessary” while keeping logic and view separate.


5  Pros & Cons according to the book

✅ Pros

  1. Clear separation of concerns—UI vs. data logic.
  2. Reusability—presentational components become flexible building blocks.
  3. Designer‑friendly—easy to tweak visuals without touching data flow.
  4. Simpler tests—pure functions are easy to snapshot or unit‑test.

⚠️ Cons

  • In small apps the extra file may feel like overkill—hooks might be simpler.

6  When should you use it?

Use‑case Recommended?
Complex screens with multiple data sources Yes—keep UI files clean
Shared UI components across pages Yes—presentational FTW
Tiny widgets with one API call Maybe—consider a hook instead
Non‑React projects Concept still applies (e.g. adapters + views)

7  Takeaways

Think “what” vs. “how.” The moment you notice UI tangled with fetching or state logic, reach for a Container/Presentational split—or a custom hook—to regain clarity.

Next in the series: Observer Pattern—stay tuned for #LearningPatterns21!


Content adapted from “Learning Patterns” (Patterns.dev, CC BY‑NC 4.0).

Top comments (0)