The Most Widely Used Pattern in React: The Container-Presentational Pattern

Maciej Poppek
3 min readAug 1, 2024

React, a JavaScript library for building user interfaces, is renowned for its flexibility and simplicity. As the library has matured, various design patterns have emerged to help developers manage complexity and build scalable applications. Among these, the Container-Presentational pattern stands out as the most widely used due to its clear separation of concerns, maintainability, and ease of testing.

Understanding the Container-Presentational Pattern

The Container-Presentational pattern divides components into two distinct categories: container components and presentational components. This separation helps developers manage state and UI logic more effectively.

1. Presentational Components:

These components are primarily concerned with how things look. They are often stateless, meaning they do not manage any state of their own.

Responsibilities:

  • Receive data and callbacks exclusively via props.
  • Focus on rendering the UI based on the received props.
  • Avoid side effects, API calls, or state management.

Characteristics:

  • Simple, reusable, and easy to test.
  • Often implemented as functional components.
interface Props {
user: {
name: string;
}
onEdit: () => void;
}

const UserProfile = ({ user, onEdit }: Props) => (
<div>
<h1>{user.name}</h1>
<button onClick={onEdit}>Edit Profile</button>
</div>
);

2. Container Components:

These components are concerned with how things work. They manage state and handle the business logic.

Responsibilities:

  • Fetch data and manage the state.
  • Pass necessary data and callbacks to presentational components.
  • Handle user interactions and side effects.

Characteristics:

  • Often implemented as class components or using hooks in functional components.
  • More complex than presentational components due to state management and side effects.
interface User {
name: string;
}

import React, { useState, useEffect } from 'react';
import UserProfile from './UserProfile.comp';

export const UserProfileContainer = () => {
const [user, setUser] = useState<null | User>(null);

useEffect(() => {
setUser({ name: 'John Doe' });
}, []);

const handleEdit = () => {
// some action
};

return user ? <UserProfile user={user} onEdit={handleEdit} /> : <div>Loading...</div>;
};

Benefits of the Container-Presentational Pattern

  1. Separation of Concerns: By separating components into presentational and container components, developers can clearly distinguish between the UI and business logic. This leads to a more modular and organized codebase.
  2. Reusability: Presentational components are typically stateless and focus on rendering the UI. This makes them highly reusable across different parts of an application.
  3. Testability: Since presentational components do not depend on the state or side effects, they are easier to test. Container components can be tested by mocking state and props, isolating business logic from UI rendering.
  4. Maintainability: With a clear division between presentation and logic, maintaining and updating code becomes more straightforward. Changes in UI design do not necessarily impact the business logic and vice versa.
  5. Readability: The pattern encourages a clean and understandable code structure, making it easier for new developers to understand and contribute to the project.

Evolution with Hooks

The introduction of React Hooks has added more flexibility to how this pattern can be implemented. Hooks like useState and useEffect allow functional components to manage state and side effects, blurring the lines between container and presentational components but retaining the core benefits of the pattern.

interface User {
name: string;
}

const UserProfileContainer = () => {
const [user, setUser] = useState<null | User>(null);

useEffect(() => {
setUser({ name: 'John Doe' });
}, []);

const handleEdit = () => {
// some action
};

return user ? <UserProfile user={user} onEdit={handleEdit} /> : <div>Loading...</div>;
};

The Container-Presentational pattern remains the most widely used pattern in React development due to its simplicity, clear separation of concerns, and enhanced maintainability. By adopting this pattern, developers can create scalable, testable, and maintainable React applications, ensuring a clean and organized codebase. While React Hooks have introduced new ways to manage state and side effects, the core principles of this pattern continue to offer significant advantages in modern React development.

If you enjoyed my article, don’t forget to leave a few claps 👏🏻 and follow me to stay updated with the articles I publish 🙂

Image by Tom from Pixabay

--

--

Maciej Poppek

A Senior? Front-end Developer working on a daily basis with JS, TS, React, and some other cool tech 🙂 https://www.linkedin.com/in/maciej-poppek/