Component Single Responsibility
Published on April 16, 2024
SOLID is a set of five principles that help you design well-structured, maintainable, and scalable code.
In this lesson we will focus on the Single Responsibility Principle
which is the S
in SOLID
.
This is a mistake I see often among React developers, and it’s a mistake that can lead to a lot of problems down the road.
If your component is very long and dealing with many different things, it’s a sign that this component is probably violating the Single Responsibility Principle
.
If a component has many if’s which render different things, or if it has many different states, or if it has many different functions that do different things, it’s a sign that this component might be violating the Single Responsibility Principle
.
Let’s examine the following component and try and improve it by following the Single Responsibility Principle
.
Take a look at the <BadTodo />
component. The component is responsible for fetching the todo items, rendering a loading sign until the response is received, rendering a list of todo items, and rendering an error if the request is failing.
Notice the multiple if’s which cause a different render, which are a clear sign that this component is breaking the Single Responsibility Principle
.
What if we want to share the loading sign with other components? What if we want to share the error message with other components? What if we want to share the list of todo items with other components? We can’t do that because this component is doing too many things.
Often breaking the Single Responsibility Principle
leads to code duplication, and it makes the code harder to maintain and test.
Let’s replace the <BadTodo />
component and instead create the <GoodTodo />
which follows the Single Responsibility Principle
.
Take a look at the following:
We are using here a few techniques to give <GoodTodo>
and all the components here a single responsibility:
- We are using a custom hook
useTodos
to fetch the todo items. This hook is responsible for fetching the todo items and nothing else. - We use
<Suspense>
and provide afallback
prop with our<Loading />
component. This way we can share the loading sign with other components, and the<Loading>
has a single responsibility. - We use
<ErrorBoundary>
and provide afallback
prop with our<Error />
component. This way we can share the error message with other components, and the<Error>
has a single responsibility.
Every thing in our app is responsible for one thing and one thing only. This makes our code easier to maintain, easier to test, and easier to extend.
We can easily share the <Loading />
and <Error />
components with other components, and we can easily share the useTodos
hook with other components.