Code Monkey home page Code Monkey logo

react-clean-architecture's Introduction

Word of advice

This is an example repo, I wouldn't do exactly like this in production. I am simply sharing one way this could be done, may not be the best, but it's a realistic way. I Recommend looking for other implementations as well to complement your research. The repo is also a bit outdated and many conventions have changed over time.

Examples (please create a PR adding any other example you have)

React Clean Architecture

Applying clean architecture to a react codebase brings lots of benefits, most of them you can find by simply googling what's clean architecture and what should we adopt architectural patterns. One advantage that strikes me is having business rules isolated from framework-specific things. This means that our core logic is not coupled to React, React Native, Express, etc...
This gives you enough flexibility to, for example, move specific parts of the application to a backend, change libraries without too much pain, test once and reuse as many times as you want, share code between React and React Native applications, among others.
This is a realistic approach, what I mean by that is: It's simple enough to be applicable and Robust enough to have it in a production environment. Although I have greatly simplified it, for educational purposes, I believe that this example is of great value to get you started with applying architectural patterns and adapting them to your own needs.

Detailed explanation

I've been pretty busy lately, so I'll write as much as possible.
I'll write three blog posts explaining better what is Clean Architecture, why adopt it and how. Portuguese version of How to implement clean architecture for React codebases can be found HERE

Philosophy

high-level-diagram

The nomenclature may vary, but the concept behind this architectural pattern is: the domain dictates how tools should be organized and not the other way around. What I mean by that is that we should organize our codebase around the business rules and not around the frameworks we use to achieve business rules. The diagram above shows how the dependency rule works, the inner circles must not know about the outer circles. That is, there cannot be an import of a use case within an entity, or import of a framework within a use case. Another important rule is: entities and use cases should not rely on external libraries. The explanation is simple, the core of our application must be robust enough and malleable enough to meet the demands of the business without needing any external intervention. If by chance, an essential part of the application core MUST BE an external dependency. Dependency needs to be modeled following dependency inversion principle.

Communication flow

communication-flow-diagram

A brief explanation of each responsibility

  • Entity: Application independent business rules
  • Interactor: Application-specific business rules
  • Adapter: Glue code from/to Interactors and Presenter, most of the time implementing a framework-specific behaviour. e. g.: We have to connect Interactor with react container, to do so, we have to connect Interactor with redux (framework) and then connect redux to container components.
  • Presenter: Maps data from/to Adapter to/from Components.
  • Components: Simplest possible unit of presentation. Any mapping, conversion, MUST be done by the Presenter.

Sample apps DEMO

Talk is cheap, don't you think? That's why I'm sharing two sample apps to facilitate your digestion.
A great advantage of following clean architecture is having all business logic self-contained and closer, in a readable way.
Take a look at core/entities/ and core/useCases/ folders and see for yourself.

Counter

The counter app is a simple example of how to apply clean architecture to react world, it uses only synchronous actions and has no external dependencies.
It contains 2 use case rules:

  • The count must not be negative.
  • The count must not be greater than 10.

counter-gif


Authentication

An authentication app is a simple example, but not that simple, of how to apply clean architecture to a realistic scenario. It contains some shared business rules:

  • Users must have a valid email.
  • Users password must comprises only numbers and/or letters.
  • Users name must have a full name, and it must to be lowercased.
  • The App cannot sign up two users with the same email address.
  • The App must use an external dependency to persist user register.

authentication-gif


Folder Structure

This repository contains 2 examples of how to implement react following clean architecture, represented by the diagram above, and both follow the same folder structure:

./counter
├── core
│   └── lib
│       ├── adapters
│       │   └── redux
│       ├── entities
│       ├── frameworks
│       └── useCases
├── native
│   └── src
│       ├── components
│       └── stylesheets
└── web
    └── src
        ├── assets
        ├── components
        └── stylesheets

Note: the frameworks folder comprises framework-specific setups to have it available to the adapters.

Running the apps

run npm install under the project you'd like to run, and then run npm start.

Running on Windows

There's an issue related to how yarn/npm symlink file dependencies on windows. Due to this issue, you should first go under the core module and run npm install and npm run build. This will make the core module ready to be installed on the other modules.

References

Thanks

Feedback

If something looks odd, don't hesitate to reach me out or opening an issue.

react-clean-architecture's People

Contributors

dependabot[bot] avatar eduardomoroni avatar luisangellopez9731 avatar nj9802 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-clean-architecture's Issues

Project is build with errors

Regards!
When I executing a command yarn start getting an error:

Failed to compile.

C:/Projects/react-clean-architecture/authentication/web/node_modules/core/dist/adapters/redux/saga.d.ts
(16,54): Cannot find module '../../../../../../../Projects/react-clean-architecture/authentication/core/node_modules/redux-saga/effects'.

And I needed to change the import path: "core": "file:../core" to "core": "../core"

System:

Windows 10
Node: 10.15.3
Yarn: 1.15.2

Question about counter

First of all, thank you for the great article. It really helped me to understand a little better how to think of a clean architecture for future projects.

In this file is it right for the increment and decrement function to return the counter entity? Doesn't it break the encapsulation/constraint that the useCase is supposed to maintain (application logic)?
e.g: counterInteractior.decrement(1).decrement(20)

Also, in the same file, this.counter = new Counter(this.higherBound) ins't it bad, not only for the performance but also for not keeping the object state (if it had more states besides the count)?

Missing script: start

Cannot start project with npm run start because of no start script in package.json.

Cant run project on windows.

So i did installation on windows like in readme.

  1. go to authentication/core - npm install && npm run build
  2. go to authentication/web - npm install && npm start

I get an error:

`[email protected] start D:\react-clean-architecture\authentication\web
react-scripts-ts start

undefined:21
},
^

SyntaxError: Unexpected token } in JSON at position 545
at JSON.parse ()
at loadTsconfig (D:\react-clean-architecture\authentication\web\node_modules\tsconfig-paths\lib\tsconfig-loader.js:72:23)
at loadSyncDefault (D:\react-clean-architecture\authentication\web\node_modules\tsconfig-paths\lib\tsconfig-loader.js:27:18)
at tsConfigLoader (D:\react-clean-architecture\authentication\web\node_modules\tsconfig-paths\lib\tsconfig-loader.js:13:22)
at configLoader (D:\react-clean-architecture\authentication\web\node_modules\tsconfig-paths\lib\config-loader.js:27:22)
at Object.loadConfig (D:\react-clean-architecture\authentication\web\node_modules\tsconfig-paths\lib\config-loader.js:8:12)
at new TsconfigPathsPlugin (D:\react-clean-architecture\authentication\web\node_modules\tsconfig-paths-webpack-plugin\lib\plugin.js:20:42)
at Object. (D:\react-clean-architecture\authentication\web\node_modules\react-scripts-ts\config\webpack.config.dev.js:127:7)
at Module._compile (internal/modules/cjs/loader.js:1138:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
at Module.load (internal/modules/cjs/loader.js:986:32)
at Function.Module._load (internal/modules/cjs/loader.js:879:14)
at Module.require (internal/modules/cjs/loader.js:1026:19)
at require (internal/modules/cjs/helpers.js:72:18)
at Object. (D:\react-clean-architecture\authentication\web\node_modules\react-scripts-ts\scripts\start.js:39:16)
at Module._compile (internal/modules/cjs/loader.js:1138:30)`

TypeScript compilation error when running pnpm build in core/ (Counter)

Hello,

I encountered an issue while running pnpm build in your project. The error message I received is:

lib/useCases/CounterInteractor.ts:20:28 - error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'.
  Type 'undefined' is not assignable to type 'number'.

20     this.counter.increment(qty);
                              ~~~


lib/useCases/CounterInteractor.ts:30:28 - error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'.
  Type 'undefined' is not assignable to type 'number'.

30     this.counter.decrement(qty);
                              ~~~

Steps to reproduce the issue:
Run pnpm install
Run pnpm build
Observe the TypeScript compilation error mentioned above.

Environment:
Operating System: Windows 11

Core npm package doesn't hot refresh upon update in the react native project

When running the project a pretty big downside is the core module won't push an update to hot refresh when running the app during development. This is a pretty significant downside during development. Perhaps the web and native modules might suffer the same problem when loaded in the package.json file as: "file:../<module_name>" as a dependency.

What's the role of use cases?

BTW feedbacks are welcome 👍🏽

Saw this in another issue, hope it's ok if I make a new one.

First of all, thanks for this repository! It helped me deepen my understanding of clean architecture.
One thing I don't quite get is the role of use cases. I know what they are supposed to do in clean architecture (implement app specific logic) but in this repository they don't really do anything, they are just a wrapper around services. They don't contain any logic and the classes declared inside the useCases directory don't do anything at all as far as I can tell. I can achieve the same result by implementing the interfaces on services and using services directly, as opposed to passing a service to a use case.
What are they meant to do?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.