Home > Net >  React - Scalable architecture without Redux (MVC DDD approach)
React - Scalable architecture without Redux (MVC DDD approach)

Time:11-18

Introduction

React is really flexible, it seems that we are not forced to follow a specific architecture when programming interfaces, unlike with other libraries, it is something like coding a plain view. With small web apps, this is cool, but... as soon as your app starts to grow, the speed with which you code will decrease progressively, contrary to if you had defined your architecture from the beginning of the principles.

My Architecture

In my case, I am not using Redux for state management... instead, I am using React Context React Hooks.

This is my current project structure (serverless app built using firebase):

/app
   /components
      /Activity
      /Authentication
      /Profile
      /Buttons
      /Text
      /Inputs
      /Giphy
      /Messaging
      /HOCs
      ...

   /screens
      /Activity
      /Authentication
      /Profile
      /Messaging
      ...
   
   /contexts
      /Users
      /Content
      /Auth
      ...

   /hooks
      /auth
      /profile
      /users
      /content
      /badges
      /i18n
      ...

   /navigation
      /Stacks
      /Tabs
      ...

   /services
      /third-party
      /firebase 
         /api
      ...

   /lib
   /theme
   /styles
   /utils


/functions (backend)

As you can notice, I am using some kind of domain-driven design to structure my project files.

Also, I am separating concerns from screens and components using hooks, and managing complex state (or which need to be synchronized between routes) inside contexts that contains the respective reducers.

This seems to me like some kind of MVC. Where the View is composed by all my React Functional Components, the controller is composed by all my Business and UI hooks, and the data of my Model is contained inside Contexts (or, at least the dynamic data, because of efficient reasons).

As you can see, I have a folder "services" which is just the interface that my business hooks use in order to connect to my server (cloud functions).

Questions

  1. Does this architecture have a name (flux/redux??)? I mean, with the passage of time as a React programmer, mistake after mistake, I have ended up organizing my projects like this, in a "natural" way.

  2. Is it an anti-pattern to split all my components logic with hooks? I mean, all the functional components of my project just contain the event handlers or the JSX to render the UI. I have moved every single block of code to hooks, some of them contain the logic of my business, others simply complex logic related to the graphical interface (animations, ...)

  3. Which advices do you give to me in order to refine my current architecture?

  4. useSelector with React Context? I have implemented some custom hooks that just read and compute derived data from contexts... as I can't use "useSelector", I don't know if this is something typical, because they just consume the necessary contexts (useContext) and then execute some calculations.

  5. Is it Redux really necessary? For a medium-large project, I have handled it well using React Context and with the help of the hooks my code has been quite clean. Do you think that over time, as the project continues to grow, it will be necessary to move to Redux?

  6. Are react hooks the controllers of an application?

CodePudding user response:

Well, not completely sure that this is the right place to put questions like this, but let try to answer, from my point of view, to these points.

Answers

  1. I don't think this specific architecture has a name (like, for example, this one, that has a name https://www.freecodecamp.org/news/scaling-your-redux-app-with-ducks-6115955638be/). In any case the name would not be "Flux" or "Redux" since these names are more related to how data is treated instead of how folders are structured in the project. I don't think there is some strict rule about folder hierarchy to follow to be fully compliant with Flux or Redux patterns. For sure there are best practices and conventions, but they are not mandatory.
  2. To answer this point, let me share this link https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0 about an article posted by Dan Abramov. I am sharing this article because of the last update made (the article is dated 2015, but there is an important update made in 2019). As you can see seems that you are doing it good since you are putting the core logic in hooks. Just a note about this point: you said "functional components" but I think you were referring to "presentation components", this is an important distinction because "functional component" means that your component is based on a function (instead of a class), "presentation component" instead means that the component does not contain business logic. A "presentation component" can be both class-based or functional and a functional component can contain business logic (class-based component are being replaced by functional ones, but this is another story).
  3. Some advice: be coherent with capitalization and casing (you are mixing uppercase and lowercase, dash-case and camelCase, usually I like to name every file or folder in dash-case, but it depends on you); nut sure if HOCs folder should be here; maybe you can put all the utils (lib, theme, styles and utils itself) in a directory called utils where each util is named property;
  4. About context, and this is a controversial topic, just want to share some considerations taken from docs https://reactjs.org/docs/context.html#before-you-use-context and share my opinion on that. The idea behind context is "Context provides a way to pass data through the component tree without having to pass props down manually at every level", as per documentation subtitle. So, basically, it si something created to avoid "property drilling", as exposed here https://medium.com/swlh/avoid-prop-drilling-with-react-context-a00392ee3d8 for example. This is just a personal point of view but, maybe, is better to introduce Redux for global state management instead of using Context API.
  5. Don't be scared to use Redux. Be scared if, while using Redux, you have tons of duplicated lines of code. In this case you should think about how to abstract your actions and reducers (for example with action creators). If you will be able to generalize stuff like "getting a list of items from your backend", you will realize that your code will not just have less lines of code than a repetitive one, but it is even more readable and coherent. For lists, for example, you may have an action like const getListOfNews = list("NEWS_LIST", "/api/news/"); where list is an action creator like const list = (resource, url) => (params = {}) => dispatch => { // your implementation... };, something similar with reducers.
  6. No, they just "let you use state and other React features without writing a class" as said here https://reactjs.org/docs/hooks-intro.html from docs. It is important to avoid trying to adapt a pattern like MVC to something that was created with different ideas, and this is a general advice. Is like if you are coming from Angular and you try to work in the same way in React. Basically you should work with React, or other libraries/frameworks, without trying to transform them from what they are to what you already know.
  • Related