How to Apply Interface Segregation Principle in ReactJS
SOLID is a set of principles that are not specific to any framework or language. These principles help us to understand how to write beautiful applications for our customers.
Today we will talk about the fourth principle of SOLID:
I: Interface Segregation Principle
We will try to understand the underlying concept of this principle and implement it in the context of ReactJS.
Previous Articles in this Series
What’s This Principle All About?
According to Stackify, the Interface Segregation Principle says
Clients should not be forced to depend upon interfaces that they do not use
In ReactJS we don’t use any interface, at least not in the sense of object-oriented programming. So the main takeaway for this scenario is:
Components should not depend on things they don’t need.
Now, let’s see how this principle can help us to write clean and beautiful ReactJS components.
A Practical Approach
Let’s say we have a User component that’s responsible for displaying the details of a user. Our user object looks something like this:
const user = {
name : "Some user",
age : "60",
adderess : "House Address",
bankName : "Some Bank",
bankAccountNumber: "1234567890"
}
However, it uses two children components, named PersonalDetails
and BankingDetails
to show the details.
Our User
component looks something like this:
import React from "react";
const user ={
// described as before
}
export const User= () => {
return <>
<PersonalDetails user={user} />
<BankingDetails user={user} />
</>
}
Similarly our PersonalDetails
looks like this:
import React from "react";
export const PersonalDetails= ({user}) => {
return <>
<div>name: {user.name}</div>
<div>name: {user.age}</div>
<div>name: {user.address}</div>
</>
}
And our BankingDetails.js looks like this:
import React from "react";
export const BankingDetails= ({user}) => {
return <>
<div>name: {user.bankName}</div>
<div>name: {user.bankAccountNumber}</div>
</>
}
So, what’s the problem with this approach? Well, two things.
Firstly, our PersonalDetails
component doesn't need banking information and our BankingDetails
component doesn't need personal details to function so it’s clearly violating the Interface Segregation Principle.
Secondly, In the future, if we want to add typescript to our project (which you should) then to test PersonalDetails
you’ll be required to mock the whole user object, though the banking information has nothing to do with PersonalDetails.
So, we need to fix this. But how?
Let’s Fix This
There are several approaches for fixing this problem, but the underlying principle is the same. > # We need to pass only the relevant information to the children components.
So we will break down our data object and pass the appropriate parts to the respective components only.
](https://cdn-images-1.medium.com/max/7888/1*uTVgTG3lCHIfK3ZNOrwL2A.png)
Something like this:
import React from "react";
const user ={
personalDetails : {
name: "Some Name",
age: "60",
address: "Some address"
},
bankingDetails : {
bankName: "Bank Name",
bankAccountNumber: "1234567809"
}
}
export const User= () => {
return <>
<PersonalDetails user={user.personalDetails} />
<BankingDetails user={user.bankingDetails} />
</>
}
We’ve broken our user data into two parts with new keys personalDetails
and bankingDetails
and we passed this specific piece of data to our child components.
The Second Approach
The previous solution is perfect, but what if you don’t have control over the data? Perhaps it’s fetched from a remote source. Or what if you don’t want to modify the data structure for some reason?
Don’t worry. We can apply another technique to solve this:
import React from "react";
const user ={
name: "Some Name",
age: "60",
address: "Some address",
bankName: "Bank Name",
bankAccountNumber: "1234567809"
}
export const User= () => {
return <>
<PersonalDetails name={user.name} age={user.age} address={user.address} />
<BankingDetails bankName={user.bankName} bankAccountNumber={user.bankAccountNumber} />
</>
}
In our child components, we can use this as the following:
import React from "react";
export const PersonalDetails= ({name , age , address}) => {
return <>
<div>name: {name}</div>
<div>name: {age}</div>
<div>name: {address}</div>
</>
}
And:
import React from "react";
export const BankingDetails= ({bankName , bankAccountNumber}) => {
return <>
<div>bankName: {bankName}</div>
<div>bankAccountNumber: {bankAccountNumber}</div>
</>
}
Now our child components only get what they need. They are cleaner and easier to understand.
Now our components don't depend on anything that they don’t need.
Final Nail in The Coffin
Up to this point, we introduced the concept of the Interface Segregation Principle to make our components tight. But in our previous article on Liskov Substitution Principle, we saw that our current solution has a problem and that is anything can be passed onto the children component.
Let’s introduce typescript in our project and solve that issue.
import React from "react";
interface IPersonalDetails {
name: string;
age: number;
address: string
}
export const PersonalDetails= ({name , age , address}: IPersonalDetails) => {
return <>
<div>name: {name}</div>
<div>name: {age}</div>
<div>name: {address}</div>
</>
}
Similarly, we can do the same to BankingDetails
component.
import React from "react";
interface IBankingDetails{
bankName: string;
bankAccountNumber: string;
}
export const BankingDetails= ({bankName , bankAccountNumber}: IBankingDetails) => {
return <>
<div>bankName: {bankName}</div>
<div>bankAccountNumber: {bankAccountNumber}</div>
</>
}
Now we are forced to pass only the relevant data to the children components. No more unwanted bugs for you!
How great is that? :D
Final Thoughts
These are just principles to guide your way of thinking — not hard and fast rules to build your application.
Knowledge of these concepts will take you ahead of others. These concepts will surely help you to understand the core principles of programming.
Because frameworks are temporary but concepts are permanent
I hope you enjoyed this article as much I enjoyed writing it. Have a Great Day!
Resources
Have something to say? Get in touch with me via LinkedIn