Presentational And Container Component With React
A basic article that explores React patterns, the uses, and differences between Presentational and Container Components.
Target Audience
This article is for both old and newbies to Reactjs. Anyone that wants to learn a pattern of building React applications.
Learning Objectives
After reading this article, you will know how to do the following:
- Identify a presentational component.
- Create a presentational component.
- Know how to use the presentational components.
- Identify a container component
- Create a container component.
- Know how to use container components.
- Differentiate presentation from container component.
This article will improve your knowledge of how to use the Presentational and Container components in React. It won't make you become an expert in React. It takes lots of consistency and practice to become one.
Introduction
I recently planned to upgrade my skills in web development from mid-lever to senior. Although, I've built and managed full-stack projects working as a freelancer. But I wasn't certain about my skill level, so I started the challenge.
A few months ago, I started studying React patterns. I learned a lot in process of learning. I have always been intentional with the way I structure my code and folder. I learned my approach was not consistent and doesn't help with the management of my codebase. This makes it harder to maintain as the gets bigger and bigger.
Now, this article discusses React component design pattern. A design pattern for building Reacts applications. This involves the separation of components into two buckets. These buckets are called presentational and container.
Presentation
It describes a pattern in React that’s concerned with how things look. It is mostly used to render data on the page. One way to do this, you create a child component that takes data from the parent component as props and renders it on the page.
The following describes a presentation better.
- How things look
- Little to no state
- Receive all data via props
- Functional Component
- Same use case as Twig templates
- Helps avoid duplication of code and markup in your react application
- Code reusability across the application
- Code Readability and maintainability
- Have no dependencies on the rest of the app.
- Pure functions
- Separation of concerns
- Testable
- Style guides
- Composition over inheritance
- No side-effects or shared state
- Declarative. Declarative programming for declarative library
- Immutable state. Immutability helps avoid render errors
- Easier to reason about component dependencies
Let’s go through the following examples:
Examples 1: ClickCounter Component
const ClickCounter = (props) => {
const [ counter, setCounter ] = useState(0);
addCounter = () => {
setCounter(counter + 1);
};
return (
<div>
<button className="btn" onClick={addCounter}>
Click blue
</button>
clicked {counter} times
</div>
);
};
Example 2: Form Component
const Form = (props) => {
const [name, setName] = useState("");
const [namesList, setNamesList] = useState([]);
const onSave = () => {
setNamesList(name);
setName("");
};
return (
<div>
<form>
Enter Name:
<input type="text" onChange={(e) => setName(e.target.value)} />
<button className="btn" onClick={onSave}>
save
</button>
</form>
<ul>
names.map(name => <li>{name}</li>)
</ul>
</div>
);
};
In the above example, the <button>
tag exists twice. One <button>
exists in the ClickCounter
component, and the other in the Form
component. However, both buttons
do similar things.
The next example uses the react Presentation component pattern. Rather than creating multiple buttons
with similar features. You convert the <ul>
tag that displays a list of names into a presentation component. And do the same for the button
tag.
Something like this:
Create a Button
component with a click functionality.
const Button = ({ label, handler }) => {
return (
<button className="btn" onClick={handler}>
{ label }
</button>
}
}
Create a Person
component that displays a list of names.
const Persons = (names) => {
return (
<ul>
names.map(name => <li>{name}</li>)
</ul>
);
};
These are what presentational components look like.
The <button>
and <ul>
tags are converted into separate components. And receives props from the parent component.
Container
It describes a pattern in React that’s concerned with how things work. It's more like the business logic of an application. It manages the states; it renders the presentational component as a child component and passes state as a child props.
The following best describes the container component.
- How things work
- Render presentational and container components
- Provide data and behavior
- Stateful
- Helps avoid duplication of code and markup in your react application
- Code reusability across the application
- Code Readability and maintainability
- Separation of concerns
- Testable
- Style guides
- Composition over inheritance
- Declarative. Declarative programming for declarative library
- Easier to reason about component dependencies
As stated above, the container component manages the states of the application and renders the presentational component as a child component. The next example uses the presentational components alongside the container components.
Both are presentational components.
const Button = ({ label, handler }) => {
return (
<button className="btn" onClick={handler}>
label
</button>
);
};
const Persons = (names) => {
return (
<ul>
names.map(name => <li>{name}</li>)
</ul>
);
};
The initial clickCounter
and Form
components do not flow with the react pattern. Because these components manage the states and render the data on the page. But, changes are made in the next example.
The following examples separate all components into two main buckets (presentational and container) components and use both together.
1. ClickCounter
Container Component
const ClickCounter = (props) => {
const [counter, setCounter] = useState(0);
const addCounter = () => {
setCounter(counter + 1);
};
return (
<div>
<Button label="Increment" handler={addCounter} />
clicked {counter} times
</div>
);
};
The ClickCounter
container component manages its own states of the application. It renders the Button
component as a child component. And passes the addCounter()
function as a child props to the Button
component.
2. Form
Container Component
const Form = (props) => {
const [name, setName] = useState("");
const [namesList, setNamesList] = useState([]);
const onSave = () => {
setNamesList(name);
setName("");
};
return (
<div>
<form>
Enter Name:
<input type="text" onChange={(e) => setName(e.target.value)} />
<Button label="Save" handler={onSave} />
</form>
<Person names={namesList} />
</div>
);
};
The Form
container component manages its own state. It renders the Button
and Person
presentational components as children components.
The Person
presentational components receive the namesList
states as props from the parent container component (Form
). The same goes for the Button
as it receives the onSave()
function as a prop.
The above code seems easier to read, manage, and reusable. Because the presentational handles the look of things. While the container manages the application.
This react pattern helps to structure your application. And also for better folder management. You section your folder into two parts. The presentational components; are components that handle the looks of the application. And the container components; are components that manage the state of the application.
Conclusion
In conclusion, this is a straightforward approach that teaches the Presentational and Container component patterns in React, and their uses. As stated above, You now know how the presentation component helps in rendering information on the page. And how the container component manages the state of the application. By now, you should know how to implement the presentational and container component pattern in your application.