Separation of concerns in React and React Native.
Tags: react, bestpractice, designpatterns, modularity
Published: 2023-05-09 15:39:15

As developers, we all know the feeling of adding new feature with screen full of codes which seems to go on forever. Whether you're a seasoned developer or just getting started, this post will give you a deeper understanding of the power of separation of concerns and how you can apply it to your own web and mobile development work. 

> **Separation of concerns** is a practice of divide our code into more `maintainable`, `reusable` and `testable` separate sections or modules which is responsible for one single purpose, specific task.

## The Power of Separation of Concerns

1. Increase Cohesion

2. Reduce Coupling

3. Clean and Maintainable.

4. Reusable across different parts of the application.

5. Easy to test.

6. Better code quality at all levels.

Overall, by using the separation of concerns in React, we can increase cohesion and reduce coupling, leading to a more maintainable and scalable codebase.


## Separation of Concerns in Action: Real-World Examples from Web Development

Let's take an example of good old-fashioned Todo app.

{% embed https://codesandbox.io/embed/todo-cr55u7?fontsize=14&hidenavigation=1&module=%2Fsrc%2FTodo.js&theme=dark&view=editor %}

While this simple Todo app may be easy to maintain in its current state, **more complex logic** and additional requirements could quickly make the codebase **difficult to manage.**

In such cases, even the most seasoned developers might hesitate to make changes, fearing that they'll break something or unknowingly introduce bugs.


## Solution


As our render function grows in size and complexity, it can become difficult to read and maintain. In order to improve **code clarity** and separation of concerns, it's a good idea to split the render function into separate **UI elements**.

By doing so, we can compartmentalise different aspects of the UI and more easily make changes or updates. Additionally, this can lead to **better code reusability** and **testability**, as each UI element can be **individually tested** and **reused** in other components as needed.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d80ase61d9oen2bds858.png)


We will explore some strategies and best practices for managing a complex app and keeping your codebase `clean`, `maintainable`, and `bug-free`.

###1. Separate JSX File.

> Responsible for for displaying **UI elements** only.

We will create a `Todo.jsx` file that exclusively contains **JSX elements**.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wuij3s43m4mbqwfxa4d9.png)

Consider creating a separate function specifically for rendering the **input**, **button** and **list** elements,

**Input element**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vxj4oak3a8tiq7f6ci05.png)

**Button Element**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/20mxsa0bxky4yc18qi1u.png)

**List Element**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ffzda18exxfgifa1gfzl.png)

We will split the `todo item` into separate component for improve maintainability.

**Todo Item**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1xor6rzt4nf9jbw8rpdh.png)

## 2. Custom Hooks 

> Responsible for handling Logics, UI events and callbacks.

For handling **Logics**, **UI Events** and **Callbacks** related to `Todo.jsx`, We will create a **custom hook** called `useTodo.js`

This will improved the maintainability and readability.

We can now test each function in isolation with any Node.js testing library, **regardless of whether it supports React components or not.**

**Let's Add State Logic,** 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/77bp49ipkzvk0ojpnk67.png)

> If this component only has a few states, it can be managed within the custom hook itself. However, if the number of states increases, it's best to create a separate file for a `reducer` and handle the states in that file to avoid cluttering the custom hook.

**Let's Add UI Events and Callbacks,**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p70vl38tasm3hladc7yz.png)


> If a component only has a few lines of JS code, it may not be necessary to separate the logic as it can be easily managed within the same file.

### 3. Utils File

> Responsible for logic and helper functions as needed.

To keep our custom hooks clean and organised, we can add any additional logic or helper functions in the `todoUtils.js` utils file.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f298pcmzjwbcsncub19q.png)

### 4. Reducer File

> Responsible for managing and manipulating data (if necessary).

Discover how combining the power of useReducer with the efficiency of Redux Toolkit can help you take your React app's performance and code quality to the next level. Check out our latest blog!

{% embed https://dev.to/sathishskdev/using-usereducer-and-redux-toolkit-together-a-powerful-combination-for-state-management-3b2h %}


### 5. Api File

> Responsible for connecting to servers.

Separating our API calls into separate files can make our code more **modular**, allowing you to easily **add** or **remove** functionality without affecting other parts of your application.

This can also make it easier to write **unit tests** for our code. We can add test each component individually, without having to worry about the larger application as a whole.

We can use Redux toolkit - [RTK Query's createApi](https://redux-toolkit.js.org/rtk-query/overview#apis) is a powerful feature of the React-Redux Toolkit that provides more number of benefits.


### 6. Style File 

> Responsible for styling JSX elements.

When our styles are organised into separate files based on functionality, it is easier to follow the **flow of our application** and understand how different parts of our code **interact** with each other.

For React, we can add **css**, **scss** and **css** modules in this styles file.

For React Native, we can add component **styles** here instead of using in component file itself.

Finally, our todo app will look like this,

{% embed https://codesandbox.io/embed/separation-of-concerns-todo-app-nu55yu?fontsize=14&hidenavigation=1&module=%2Fsrc%2Ftodo%2FTodo.jsx&theme=dark&view=editor %}


##Key Learnings: Implementing Separation of Concern

By separating concerns in this way, we have made testing our code much more manageable. Instead of testing the entire component's code, we can now test each function in isolation with any Node.js testing library, **regardless of whether it supports React components or not.**

This also means that we can **reuse** these functions in other parts of our application, making them more **flexible** and **maintainable**. 

By keeping our **framework-specific code** in the component and the hook, and our **business logic** in separate functions, we have created a more modular and extensible codebase that is easier to reason about and maintain.

If a component only has a few lines of JS code, it may not be necessary to separate the logic as it can be easily managed within the same file.

You can check this entire code in [Code sandbox](https://codesandbox.io/s/separation-of-concerns-todo-app-nu55yu?file=/src/todo/Todo.jsx) and [GitHub](https://github.com/sathish-sk-dev/todo-soc).

Please give your feedback and questions on comments section.

Happy Coding!!