Categories: softare development

React Clean Architecture

React Clean Architecture applies the principles of Clean Architecture (introduced by Robert C. Martin, “Uncle Bob”) to frontend development. The goal is to build applications that are scalable, testable, maintainable, and easy to extend—even as your project grows large.

Why Clean Architecture in React?

As React apps grow, they often become messy:

  • Components handle business logic.
  • API calls are scattered everywhere.
  • UI and logic tightly coupled.
  • Hard to test or reuse code.

Clean Architecture solves these by enforcing separation of concerns and layered boundaries.

Learn React Online

Core Principles

  1. Dependency Inversion
    Inner layers must not depend on outer layers.
    Example: business rules should not depend on React components.
  2. Separation of Concerns
    Each layer has a single purpose (UI, logic, data).
  3. Testability
    With isolated layers, unit tests become easier.
  4. Maintainability
    New features can be added without breaking unrelated areas.

React Clean Architecture Layers

Clean Architecture divides the app into four major layers:

1. Presentation Layer (React Components)

This is where your pages, components, routes, and UI live.

Responsibilities:

  • Display data to users.
  • Collect user input.
  • Call use cases (business rules).
  • No business or API logic.

Example:

function LoginPage({ login }) {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  const handleSubmit = () => login({ email, password });

  return (
    <div>
      <input onChange={e => setEmail(e.target.value)} />
      <input type="password" onChange={e => setPassword(e.target.value)} />
      <button onClick={handleSubmit}>Login</button>
    </div>
  );
}

2. Domain Layer (Business Rules)

This is the heart of your app.
It contains entities, business logic, interfaces, and use cases.

What lives here?

  • Entities (core models)
  • Use cases / services
  • Pure business logic
  • Validations
  • Interfaces (contracts)

Example Use Case:

export function loginUserUseCase(authRepository) {
  return async (credentials) => {
    if (!credentials.email || !credentials.password) {
      throw new Error("Missing fields");
    }
    return authRepository.login(credentials);
  };
}

Domain layer has no knowledge of HTTP, UI, or databases.

3. Data Layer (APIs, DBs, External Services)

Implements the interfaces defined in the domain layer.

Responsibilities:

  • Calling APIs
  • Implementing repositories
  • Handling local storage
  • Mapping responses to domain entities

Repository Example:

export class AuthRepositoryImpl {
  constructor(apiClient) {
    this.apiClient = apiClient;
  }

  async login(credentials) {
    const response = await this.apiClient.post("/login", credentials);
    return response.data;
  }
}

4. Infrastructure Layer

Everything framework-specific or technical details:

Examples:

  • Axios instance
  • Firebase config
  • Local storage utilities
  • Logging tools

Example:

import axios from "axios";

export const apiClient = axios.create({
  baseURL: "https://api.example.com",
});

How the Layers Talk to Each Other

UI (React)
   ↓
Use Cases (Domain)
   ↓
Repositories (Data)
   ↓
API/Database (Infrastructure)

But not in reverse.

The domain layer never imports React, never imports Axios, and never imports APIs.

Folder Structure Example

A recommended project structure:

src/
 ├─ presentation/          # UI: components, pages, hooks
 │   ├─ components/
 │   ├─ pages/
 │   └─ routes/
 │
 ├─ domain/                # business logic
 │   ├─ entities/
 │   ├─ usecases/
 │   └─ repositories/
 │
 ├─ data/                  # API + repository implementations
 │   ├─ repositories/
 │   └─ mappers/
 │
 ├─ infrastructure/        # Framework-specific implementations
 │   └─ http/
 │
 └─ app/                   # DI container, providers
     └─ container.js

Dependency Injection (DI)

In React Clean Architecture, DI is used to assemble dependencies.

Example Container:

import { apiClient } from "../infrastructure/http/apiClient";
import { AuthRepositoryImpl } from "../data/repositories/AuthRepositoryImpl";
import { loginUserUseCase } from "../domain/usecases/loginUserUseCase";

const authRepository = new AuthRepositoryImpl(apiClient);

export const loginUser = loginUserUseCase(authRepository);

Then pass use cases to components.

Benefits of Using Clean Architecture in React

Scalability

Large apps remain organized.

Reusability

Business rules can be reused across different UIs (React Native, Next.js, etc).

Testing

Domain and data logic are easy to unit test because they are pure.

Flexibility

Swap APIs, change UI, or change data sources without breaking the core logic.

Team Collaboration

Backend, frontend, and mobile teams can align on use cases and entities.

Real-World Example

For a login flow:

  • UI: only takes email + password and calls loginUser.
  • Domain: validates credentials and defines the login use case.
  • Data: communicates with /login endpoint.
  • Infrastructure: Axios handles HTTP.

Result: clean, decoupled, replaceable logic.

Conclusion

React Clean Architecture is not a strict rulebook—it’s a systematic way of organizing your app so it remains:

  • Clean
  • Scalable
  • Replaceable
  • Testable
  • Future-proof

Whether you’re building a small app or a production-level system, Clean Architecture gives your code clarity and purpose.

If you want, I can also create:

Share
Published by
codeflare

Recent Posts

The Golden Ratio (φ)

1. What Is the Golden Ratio? The Golden Ratio, represented by the Greek letter φ (phi), is…

6 days ago

CSS Combinators

In CSS, combinators define relationships between selectors. Instead of selecting elements individually, combinators allow you to target elements based…

1 week ago

Boolean Algebra

Below is a comprehensive, beginner-friendly, yet deeply detailed guide to Boolean Algebra, complete with definitions, laws,…

1 week ago

Why It’s Difficult to Debug Other People’s Code (And what Can be Done About it)

Debugging your own code is hard enough — debugging someone else’s code is a whole…

1 week ago

Complete Git Commands

Git is a free, open-source distributed version control system created by Linus Torvalds.It helps developers: Learn how to…

2 weeks ago

Bubble Sort Algorithm

Bubble Sort is one of the simplest sorting algorithms in computer science. Although it’s not…

2 weeks ago