Josué Hernández
The Container-Presenter pattern is a design pattern in React that promotes a clean and maintainable architecture by separating the business logic from the UI presentation. This approach ensures that components remain reusable, testable, and easier to maintain, especially as your application scales.
The Container-Presenter pattern involves splitting components into two distinct types:
Below is a practical example of implementing the Container-Presenter pattern to handle data fetching, loading states, and error management while keeping the UI rendering isolated.
import { useEffect, useState } from "react";
import { DataPresenter } from "./DataPresenter";
type DataItem = {
id: number;
name: string;
description: string;
image: string;
};
export const DataContainer = () => {
const [data, setData] = useState<DataItem[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch("/data/data.json");
if (!response.ok) {
throw new Error("Failed to load data");
}
const result = await response.json();
setData(result);
} catch (error) {
setError(`Error loading data: ${(error as Error).message}`);
} finally {
setLoading(false);
}
};
fetchData();
}, []);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error! {error}</p>;
return <DataPresenter data={data} />;
};
import React from "react";
type DataItem = {
id: number;
name: string;
description: string;
image: string;
};
type DataPresenterProps = {
data: DataItem[];
};
export const DataPresenter: React.FC<DataPresenterProps> = ({ data }) => {
if (!data.length) {
return <p>No data available.</p>;
}
return (
<div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: "10px" }}>
{data.map((item) => (
<div key={item.id} style={{ border: "1px solid #ddd", padding: "10px" }}>
<img src={item.image} alt={item.name} style={{ width: "100%", height: "auto" }} />
<h3>{item.name}</h3>
<p>{item.description}</p>
</div>
))}
</div>
);
};
The Container-Presenter pattern is a proven technique for building scalable, maintainable, and reusable components in React applications. By separating the business logic from the UI presentation, developers can create flexible components that are easier to test, maintain, and reuse.
This pattern is particularly useful for data-heavy applications, large-scale projects, or any scenario where maintainability is a priority.
In future posts, we'll explore how to combine this pattern with state management tools and advanced component design patterns to create even more powerful and dynamic applications.