SOLID is nothing: try now for React or React Native
Understand SOLID with clear examples
In this article, I’m not going to give you the standard definitions of the SOLID principles. Because it’s confusing for many developers out there. After going through this article you will understand the real-world use cases of SOLID with simple and understandable definitions. Especially how to follow SOLID in your React or React Native project.
SOLID principles are some guidelines in the development world that we can follow to build awesome components. In other words, your code will become easier to maintain, understand, and extend.
I want to mention that sometimes it could be difficult to follow the SOLID principle everywhere in your application. The best way is to first understand how to use them and act accordingly.
1. Single Responsibility Principle
This means your component should do only one thing. Thats all. Nothing else.
See what the ProfileScreen looks like at the beginning(in red). It renders a lot and handles different functionality in it such as toggling theme and notification preferences. Too many distinct responsibilities.
But after the refactoring, ProfileScreen becomes very simple and what it does is just render its children. UserInformation just renders user information. UserSettings handle the settings. ProfileScreen does not need to worry about that anymore.
Benefits:
- Easier to Understand: Clearer and more straightforward.
- Easier to Maintain: Bugs are easier to track down and fixes tend to be simpler because changes are localized to specific functionalities.
- Reduced Impact of Changes: Changing the behavior of a component that follows SRP is less likely to affect other components.
2. Open/Closed Principle
This means the component you have built should not be touched for modifications. However, you should be able to use the component to create a new extended version.
Apologies I had to add two images to explain this principle.
Imagine you have already developed the ActionButton component and using it in the application. Later a new requirement comes as adding the ActionButton to the Settings screen as shown in the diagram. But there is something new here which is the horizontal divider between two settings in the Settings screen.
One might argue you could add some border bottom styling to the ActionButton component. But that violates the open/closed principle. So my suggestion is creating a new component SettingsActionButton. Also, you can create a Divider component, not only for this requirement but you will be able to reuse it later. You can see the code snippet for SettingsActionButton in the second image.
Benefits:
- Enhanced Scalability: New functionalities can be added with minimal changes to existing code.
- Reduced Risk: Extending systems without modifying existing code means there is less chance of introducing new bugs into the existing system.
- Promotes Reusability: Components can be reused because they can be extended to fit new situations without needing to be modified.
3. Liskov Substitution Principle
This means you could be able to replace your base component with your extended component without any issues.
Here the Message component acts as the Base component. AlertMessage component acts as the Extended component which has some more stylings than the Message component. Additionally, both the components take the same props as the input. So if we are following the Liskov Substitution Principle, we could replace the places where we are using the Message component with the AlertMessage component and the system runs without any issues.
Benefits:
- Increased Reliability: Ensures that a derived class/function does not affect the behavior and expectations of the base class/function.
- Improved Code Robustness: Promotes the correctness of any hierarchies of inheritable classes/functions.
- Interchangeability: Components can be replaced with their derivatives without affecting the functioning of the system.
4. Interface Segregation Principle
This means you should not be passing any props to a component it does not need.
As shown in the above image, passing the entire parent object to the ChildInformation violates the Interface Segregation principle(in red). Because the parent object has the parent’s name and email which isn’t needed by the ChildInformation component. Instead, you should only pass the child info to the ChildInformation component.
Benefits:
- Reduced Side Effects: Changing the behavior of a component that’s used by many other components will have fewer side effects.
- Increased Cohesion: This leads to a more focused and narrow interface that promotes cohesion.
- Easier Evolution: Systems are easier to refactor, change, and redeploy.
5. Dependency Inversion Principle
This means your component should not be directly contacting with third-party dependencies.
As shown in the above code, ProfileScreen(in red) depends on redux hooks such as useDispatch and useSelector. That violates the Dependency Inversion Principle. So the correct approach I suggest is that you can pass the redux part to a custom hook useCustomHook.
Now the ProfileScreen connects to the useCustomHook. Therefore, the screen component does not depend on the redux anymore. In the future, if you decide to change your redux state management tool with MobX, you won’t be having changes in ProfileScreen. useCustomHook is the one that will get affected and the ProfileScreen component doesn’t care about that as long as it can access the info it used to access from the useCustomHook.
Benefits:
- Flexibility: Higher-level modules remain unaffected by changes in lower-level modules and details.
- Decoupling: Promotes loose coupling between the code components, enhancing reusability and flexibility.
- Easier Testing: Independent high-level components can be tested easily in isolation from other components.
Conclusion
In this article, I have covered how we can apply SOLID principles in React or React Native applications. Especially with the functional components. Hope you all have learned something new. If you think I have made any mistakes when expressing the above content, do let me know in the comment section. I will update the article accordingly. After all, we all are learning. See you all in a new article soon. Cheers!