DEV Community

Discussion on: Moving away from ReactJs and VueJs on front-end using Clean Architecture

 
rockson_30 profile image
Rockson • Edited

I mean, you can consider react-dom the actual interpreter for react, but anyway we are talking about React as a whole. Of course if you start splitting its pieces it becomes less of a framework. So is angular, if you take a single element from it like the rxstore well its not a framework on his own

Just because the react team decided to separate react and react-dom in two different dependencies and allowed people to write their own "interpreter", it doesn't mean it's not a framework.

Thread Thread
 
joelbonetr profile image
JoelBonetR 🥇 • Edited

While Angular is a complete solution (a framework), React only takes care of rendering the view and making sure that the view is in sync with the state. That's all react does, nothing less, nothing more.

If you want React to become a framework (it is not possible by itself as discussed above) you'll need other libs to compose an actual framework-like library compound that matches all the requirements of being considered as a framework, shipped together -and maintained- as a single agnostic set shipped as a base solution where to build new projects on.

@peerreynders the first call to the component is done by you inside a react render function, it's not handled by react out of the box nor even has a default required structure.
You can call componentDidMount() or not (same as other methods), you can call render() without having to call other specific method as requirement, you can define and manage your state at your own way...
You can even create your component inside the same app directory tree that does not fit into react and push it right in between the other components at the time you want (of course without using React), because react is a lib and you enforce the usage of a lib wherever you want and not vice-versa.

If you use react features (rendering the view and making sure that the view is in sync with the state) which are defined and controlled by yourself (with the React API) you simply added reactive functionality to your App using React lib.
If your App is completely based into react way to work it was your architectural decision same that happen when you use Redux -which enforces you to apply Reducer design pattern using functional programming paradigm-, then you can say Redux is a framework but again, it is not, it's intended for state management only and it's a lib.

YouTube:

Thread Thread
 
peerreynders profile image
peerreynders • Edited

That's all react does, nothing less, nothing more.

You are simply making a case that React isn't an application framework. Just because React isn't an application framework isn't evidence that it's just a library.

If you want React to become a framework

When I mean application framework I state application framework. Framework is not synonymous with application framework.

the first call to the component is done by you inside a react render function, it's not handled by react out of the box nor even has a default required structure.

ReactDOM.render(<App />, document.getElementById("root"));
Enter fullscreen mode Exit fullscreen mode

is

ReactDOM.render( 
  React.createElement(App, null), 
  document.getElementById("root")
);
Enter fullscreen mode Exit fullscreen mode

You're handing the component tree over to the React renderer via the name/reference to the function or class that represents the root of your component tree:

React here is the component tree that represents my application, could you please run my application for me …

… exactly like one does for a framework. Given that Preact doesn't have a native renderer it's even clearer

  import { h, render } from 'preact';

  // Create your app
  const app = h('h1', null, 'Hello World!');

  render(app, document.body);
Enter fullscreen mode Exit fullscreen mode

With a library:

  • The application code is primarily run from the JavaScript event loop and the application code calls the library only temporarily relinquishing control to the library. When the library completes its task it returns full control control back to the application without leaving a trace of itself on the call stack, microtask queue or task queue (within reason).

With a framework:

  • The application code is run by the framework. Once the framework is started, it runs until the application finally exits while in the meantime orchestrating most of the application activity.

A React application is run by React - not the JS event loop - React (for the most part) sits between the application and the JS event loop.

By the nature in which it operates React is a framework and not a mere library.

Now some people claim that is doesn't matter whether React is a framework or a library - but it does. Lots of sources claim that React is "unopinionated".

It's less opinionated than Angular but that doesn't mean React is unopinionated. As it operates as a framework it creates considerable design pressure towards the "React is your Application" architectural style (which isn't in your long term interest; I argue that React's pit of success herds you towards this style) - and that is opinionated. Going with a "React is not your Application" style (which this article advocates) is considerably more work largely due to React being opinionated.


If you are using react-redux you are still practicing "React is your Application". To move to "React is not your Application" you would put Redux behind an application specific façade.

Thread Thread
 
joelbonetr profile image
JoelBonetR 🥇

"You are simply making a case that React isn't an application framework. Just because React isn't an application framework isn't evidence that it's just a library."
I think I explained all key differences between a framework and a lib already, you can't simply stick to a given implementation or a single key feature and say "hey, this does not fit 100% with the given description/explanation".

The react-dom is a package that provides DOM-specific methods that can be used at the top level of your app and as an escape hatch to get outside of the React model if you need to. Most of your components should not need to use this module.

When you call

ReactDOM.render(, document.getElementById("root"));

Here you are saying, hey ReactDOM, please RENDER this component in this container.

YOU are calling the package method passing the required stuff because you added React-DOM for a specific feature, if you don't like nor want React-DOM approach you can write down your own code instead and use it along with React (which does not include React-DOM by default) or simply avoid using it.
Again is your decision whether to use it, where and how (as long as you use it according to the reference if you do, of course).

You can add more or less packages or libs into an application to extend functionality (that's what a lib does) and define -or not- your app structure depending on a lib or not.

Does this seem like inversion of control to you?

Do you really think it enforces you to do the things on a single way? Even JSX is optional and not required to use React!
You can also wrap an imperative UI into a declarative component, and vice versa.

The control over scheduling would be harder if the user directly compose views with a “push” based paradigm common in some variations of Functional Reactive Programming.

To bring reactive, some popular libraries implement the “push” approach functionality where computations are performed when the new data is available. React, however, sticks to the “pull” approach where computations can be delayed until necessary.

This means that your components (either user-written or platform specific) are declarative functions that returns a description about what needs to be done.
Then you pass this description to React and React will call this component whenever is necessary. It's just a matter of the architecture design behind it.
At the end, you are defining what needs to be done, how and where. React simply adds the when -generically speaking- while you keep the control over the process with some methods such componentDidMount

React is not a generic data processing library. It is a library for building user interfaces.

Whenever you like it or not there need to be a deep understanding of both programming paradigms and design patterns to fully understand that in deep.
Extrapolate a single thing in favour to this counter-culture is just populism that hurt -like any populism does- the community, specially those who can keep this in mind while learning and so having a hard time trying to understand the underlying tech -which is quite good and strict into it's decisions- specially design decisions.

Thread Thread
 
peerreynders profile image
peerreynders

I think I explained all key differences between a framework and a lib already.

You informed me of your opinion and you keep saying "framework" when you actually mean "application framework". While all "application frameworks" are "frameworks" not all "frameworks" are "application frameworks".

The discussion is "library" vs "framework" - not "library" vs "application framework".

you can't simply stick to a given implementation or a single key feature

Sure I can and the TLDNR is (I repeat):

  • If your code calls it, it's a library.
  • If it calls your code, it's a framework.

This is a distillation from Designing Reusable Classes 1988 - 25 years before React:

The framework often plays the role of the main program in coordinating and sequencing application activity.

React calls user components giving them a chance to update component instance state and initiate application activities - ✔.

This inversion of control gives frameworks the power to serve as extensible skeletons. The methods supplied by the user tailor the generic algorithms defined in the framework for a particular application.

React: "The components supplied by the user tailor the generic rendering algorithm in the framework for a particular application" - ✔.

A framework's application specific behavior is usually defined by adding methods to subclasses of one or more of its classes.

React: "A framework's application specific behavior is usually defined by composing components" which themselves are created by:

  • Using createReactClass which "subclasses" an internal React type via a specification object.
  • Extending React.Component explicitly.
  • Or representing a component via a function complying to a type specification (and supplying services like hooks) that can be used to access and mutate an internal React component instance while rendering its state.

So - ✔.

In 2005 (8 years before React) Martin Fowler summarized that as:

  • A library is essentially a set of functions that you can call.
  • The framework's code then calls your code

React components "plug into" React when the component tree is passed to React and React uses that tree for the remainder of the application's runtime to drive all application activity. So - ✔.

Now by this point it's contrasting a library as just a bunch of helper functions (that don't take control of application activities for the remainder of the application session) vs a framework which drives the application's activities for the lifetime of the application session.

The reason that distinction is important is because frameworks (engines of application activity) put a much larger design pressure on solution architecture than libraries. That is the core point of Architecture the Lost Years. The same way all Rails applications "looked all the same" (despite application specialization) back then, many React-based front end solutions "look the same" burying the all important "application-logic" as bits-and-pieces inside them rather than emphasizing and delineating the application-logic through architecture.

Here you are saying, hey ReactDOM, please RENDER this component in this container.

… for the remainder of the application session while the container still exists - that is an important detail. For a library it would just render it once and return - a re-render would require a separate invocation.

Does this seem like inversion of control to you?

Your components are invoked by React - that is IoC in action - React is calling your code when it deems fit.

Do you really think it enforces you to do the things on a single way?

Because React is acting as the driver of application activity it imposes design pressures to write the application in a certain way. Going against those design pressures is going to require additional effort - i.e. it's easier to just give in even if the long term consequences are detrimental (maintainability mostly).

You can also wrap an imperative UI into a declarative component, and vice versa.

It's only declarative in relation to its position in the component tree which is fine if it's just a visual, dumb component - but more often than not React components also absorb application logic and the application-logic has entirely different communication pathways than what the component tree can represent - typically application communication is just kitchen-sinked via Context.

It is a library for building user interfaces.

React drives application activity via it's components - a UI library is driven by the running application, i.e. a UI library is called whenever the UI needs to change.

Thread Thread
 
joelbonetr profile image
JoelBonetR 🥇 • Edited

wow wow wow, hold your tights. You are blending different concepts into the same speech. Let's break things down as Uncle bob said in the past.

In the "Architecture, the lost years" he's talking about MVC (which is an architectural design pattern) but let's stay apart from that for a moment would you?

You say I'm talking about application framework, that's correct so let's see which kind of frameworks we can find:

  • Technology Framework
  • Business/Enterprise Framework
  • Application Framework
  • Component Framework

Technology Framework

Provides a standard, generic software foundation.
Java is a technology framework, JavaScript is other technology framework etc


Business/Enterprise Framework

A complete environment for developing and implementing a comprehensive information system. Enterprise frameworks provide pre-built applications, development tools for customising and integrating those applications to existing ones as well as developing new applications.
They may also provide a workflow component.
Frameworks such as ERP and CRM are available for business functions such as order entry, inventory and payroll (Comparison of accounting software), while frameworks exist for specific industries such as health services and insurance.


Application Framework

Is a set of common software routines that provides a foundation structure for developing an application (Explained in detail some comments above with all key features).


Component Framework

In essence, component-frameworks break the system down into variant "components" that represent abstract processing that the system supports. These components are generally thought of as "pluggable" in the sense that the system can be configured with a set of components to accomplish a particular task or set of tasks. In many systems, the components can dynamically swapped in and out. The framework, on the other hand, is the invariant "superstructure" that manages the components, providing services to each component that, when combined with the services/behaviours supplied by that component, create the net behaviour defined by that component in that framework.

The framework has the effect of decoupling or isolating the components from each other since it the component interactions are handled by the framework in a manner that is opaque to the components.
Note that this does not preclude any ability of the components to communicate with each other outside of the confines of the framework, they are only decoupled with respect to their interactions through the framework.

One of the key and arguably, defining, characteristics of a component-framework system is its "inversion of control" or "Hollywood Principle": "Don't call us, we'll call you!" Since the framework portion of the system represents the invariant aspects of the system that mediates the dynamics of the variant components, control of the system must be delegated to the framework because the components are only providing services to the framework and are unaware of how those services interact with each other. In other words, it is the framework that is "running the show", directing the calls to the component services, not the other way around. Inversion of control virtually eliminates flow control in the components and thus reduces code complexity in the components.


Ok now let's talk about IOC (inversion of control).

Inversion of control is a design pattern principle in software design, specially (but not exclusive) Object Oriented software, that helps to keep it -among other things- loosely coupled.

One of the methods of achieving it is through Dependency Injection.

This small example of a pseudo code getting data from a database and displaying it:

// design implementation 1

class MyScreenRenderer {

   constructor() {
       this.dbQuery = new MyDBClass();
   }
   
   const showDataOnScreen = () => {
       Screen.show(this.dbQuery.getMyData());
   }
   
}
// design implementation 2
class MyScreenRendererWithDependencyInjection {

   constructor(dbHandlerInjected) {
       this.dbQuery = dbHandlerInjected
   }
   
   const showDataOnScreen = () => {
       Screen.show(this.dbQuery.getMyData());
   }
   
}

In simple terms, the later class uses Dependency Injection pattern to get a instance of some database handler it needs, but, instead of creating it, and therefore getting coupled with a specific implementation, the instance gets injected into it. This pattern makes possible to our system to change databases freely without having to change the client class.

You can learn more in the great Martin Fowler Article.

Now, in the React components, props, etc, you can apply these concepts in order to make components independent and exchangeable.

The Render Props technique for example, allows you to create a component that gets the data and render it using another component that it knows nothing about, the renderer gets injected into it.

You being able to apply this design pattern principle does not mean that React forces you to apply it. It's your decision in software design but you can simply don't apply those concepts.

Just found this post about Use the Inversion of Control pattern with React, take a look at it, it may help you understand the insights.

Thread Thread
 
fabiorizzelloomnia profile image
fabio-rizzello-omnia • Edited

Angular doesn't force you to use dependency injection too. You can declare an instance, import, and use it. That's with any framework.

Thread Thread
 
joelbonetr profile image
JoelBonetR 🥇

yup but Angular is a complete solution that covers all keys for being a framework while react does not.
There's a big difference son something being X and using something as X.
Fresh cheese can be used as salad dressing (adding other things such at least salad) while itself is not a dressing, even further you can add some syrup as dressing for fresh cheese.

That's what I'm trying to say, you can add a bunch of libs together putting React as your top lib and say "hey I got a framework" but react itself does not cover the requirements for being one and even react can be a lib to extend functionality inside another framework.

Thread Thread
 
fabiorizzelloomnia profile image
fabio-rizzello-omnia • Edited

Yes but tbh that looks more like the definition of non opinionated rather than library.
You are kinda comparing React to Angular's View Engine. Yes, Angular's View Engine is not a framework, it's used inside a framework. But when we talk about React we are talking about the combination of react + react-dom. If you take react alone it might be just like Angular's View Engine

Thread Thread
 
joelbonetr profile image
JoelBonetR 🥇 • Edited

React brings (optionally) so little list of things that I can even type a short list here:

  • React
  • React.Component
  • ReactDOM
  • ReactDOMServer
  • DOM Elements
  • SyntheticEvent
  • Test Utilities
  • Test Renderer

*From React API Doc


Angular includes many more tools -of course it does, it's an entire framework, a complete solution- that you can check at Angular API Doc


You may notice that React needs third party libs even for routing while as I said many times, Angular is an Application framework which uses components as base paradigm , being a framework means it's a complete solution. They of course can break angular down and ship separate libs as optional, but they didn't, they choose to offer a complete framework while React team decided to offer a lib which solves specific needs standardising them for anyone who uses React, maintaining it on it's little scope, instead going further and adding all the things that React currently lacks for being a framework.

Thread Thread
 
fabiorizzelloomnia profile image
fabio-rizzello-omnia • Edited

Yes but still, that's not the definition of a framework
Having many tools != Being a Framework
Having only 1 way to do things != Being a framework

"Being a framework means it's a complete solution"
Well, we might need to define "complete solution" here. Who said that a global store, http routing, animations etc... are mandatory for A framework?

As said before by others, being an application framework is a different thing.
If you want an application framework there are many in React land like nextjs and gatsby.

Still, nextjs that is labeled as an application framework doesn't have tools that angular has like animations, http, localization etc.
Nobody ever specified which tools you need to be an application framework.

Tbh I feel like the word framework is being misused everywhere these days, as if being a framework means:

  1. being opinionated
  2. having batteries included

But that's not the case, not every framework is like that

The only valid point i've seen for being framework is:
it calls you, so it's a framework

And that's the case of react + reactdom

Thread Thread
 
joelbonetr profile image
JoelBonetR 🥇

whatever man, send an email to React team with your complains to see if they change its own description. I can explain things for the community but this became a fight with your stubbornness instead.

Thread Thread
 
fabiorizzelloomnia profile image
fabio-rizzello-omnia • Edited

Looks like community doesn't agree with you either.
"send an email to React team with your complains to see if they change its own description"
Just because others say something, it doesn't mean it's true :D Not even creators

Thread Thread
 
joelbonetr profile image
JoelBonetR 🥇 • Edited

You stick to a single key feature that is IOC, after demonstrating that you can get IOC or not with react -depending on the implementation- then you say something about angular.
Read this again and do a checklist point per point and you'll end up with the same conclusion.

React is great not being a framework because it is so minimal and deals with so little that a developer will have to learn JavaScript anyway to deal with bigger problems that React JS cannot solve.

If you want to know more, please, ask Google "Why React is not a framework" and you can start a war on any place that you feel like with the same vague arguments.

You can start here for example.

Thread Thread
 
peerreynders profile image
peerreynders • Edited

In the "Architecture, the lost years" he's talking about MVC (which is an architectural design pattern)

If you had actually watched the video rather than just glanced at the thumbnail you would have realized that MVC was only a minor aside around 29:00 and that he considers MVC a design pattern

MVC is not an architecture

and that he really doesn't like Web MVC.

Aside: MVC: misunderstood for 37 years

He's at a Ruby conference and he's talking about how Rails applications in general don't have an architecture that clearly manifests the nature of the application being implemented other than that they're implemented with Rails.

Similarly many React applications have a "same-ish" structure without a clear demarcation where the UI ends and the application(-logic) begins.

In 2011 SPAs weren't commonplace so client-side architecture wasn't a discussion point (though Martin Fowler brought up Segregated DOM in 2014).

In Make the Magic go away Robert C. Martin even calls rxJava (ReactiveX) a framework which most people would classify as a library. However going "all in" with RX has a framework-like effect on solution architecture.

so let's see which kind of frameworks we can find

Wrong frame.
What are the characteristics that most if not all frameworks share? The key one in Johnson and Foote:

The framework often plays the role of the main program in coordinating and sequencing application activity.

React is invoking your components for the lifetime of the application session so as far as your components are concerned React is their "main program". And the way many if not most React components are authored - i.e. components include a fragment of the application logic - React becomes the "main program" for the entire application.

That being said, lets look at your "Component Framework" write up:

These components are generally thought of as "pluggable" in the sense that the system can be configured with a set of components to accomplish a particular task or set of tasks.

Your React components plug into React

  • to render markup in a way that is specific to your application
  • to trigger application activities, which in turn may modify component instance state causing React to schedule them for re-render.

The framework, on the other hand, is the invariant "superstructure" that manages the components, providing services to each component that, when combined with the services/behaviours supplied by that component, create the net behaviour defined by that component in that framework.

React definitely manages React components, delivers events to the component instances via its synthetic event system, delivers props from owner component instances to the nested component, renders the DOM on behalf of the component based the generated ReactNode (a framework specific type) and provides application infrastructure like Context - all of which can be considered services for the components and all for the purpose of rendering the UI and running the application activities.

type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;
Enter fullscreen mode Exit fullscreen mode

The framework has the effect of decoupling or isolating the components from each other since it the component interactions are handled by the framework in a manner that is opaque to the components.

React components don't interact directly with one another. All interactions go through React facilitated by the ReactNode objects generated by the components.

In other words, it is the framework that is "running the show", directing the calls to the component services, not the other way around.

That's React. Calls the component to get the rendered ReactNode and to schedule the application effects.

Also "Hollywood Principle":

"Don't call us, we'll call you"_

Relevant when you are writing a class/component that must fit into the constraints of an existing framework. You implement the interfaces, you get registered. You get called when the time is right.

This requires a distinctly different way of thinking from that which is taught in introductory programming where the student dictates the flow of control.

That pretty much describes React components.

So React is a component framework.

Hence the title of my gist : React is a (view component) framework.

Now, in the React components, props, etc, you can apply these concepts in order to make components independent and exchangeable.

The objective of dependency-injecting a database is to treat the database as an implementation detail. What persistence storage product is ultimately used should not affect your application's ability to function.

Your UI layout and behaviour on the other hand is specific to the needs your application - and ideally it's the UI technology (e.g. React) that you want to treat as an implementation detail, so it's React that you want to be exchangeable. Given that isn't possible, the standard tactic is to make the UI as dumb as possible (The Humble Dialog Box) and inject the whole UI as a single plugin into the application. That isn't what typically happens with React applications - typically the application is injected into React via the component tree.

The "component exchange-ability" argument is largely associated with the component reuse and replace-ability objective which is an entirely different goal. And you have to specifically design for components to adhere to a specific interface (what props, which context) to be independent and exchangeable so that isn't a by default feature, you have to put in some extra effort in for that to happen. And after all that it's still only reusable within React.

You can learn more in the great Martin Fowler Article.

Read it many times since its publication in 2004. The component tree is injected into React before anything else can happen - so React is in control.

The Render Props technique for example, allows you to create a component that gets the data and render it using another component that it knows nothing about, the renderer gets injected into it

And it has never occurred to you that it's kind of strange that a "UI library" needs support for non-visual components? You are injecting parts of the application into the UI. This is just further evidence that React is a framework.

it may help you understand the insights.

The first thing that I notice is that it's React-centric. Other than that nothing new.

And that may point to the underlying problem - in the mind of some people React is the center of the universe because React is the center of their applications.

To properly decouple the application from React it better look something like:

import { h, render } from 'preact';
import { UI } from './components/ui.jsx';
import { Shop } from './components/shop.js';
import { makeShop } from './app/shop.js';

const shop = (() => {
  const client = {
    getBooks: () => fetch('/books.json').then(response => response.json())
  };

  return makeShop(client);
})();

render(
  <App />,
  document.getElementById('root')
);

function App(_props) {
  return (
    <Shop.Provider value={ shop }>
      <UI />
    </Shop.Provider>
  );
}
Enter fullscreen mode Exit fullscreen mode

that is, your components access nothing but React or the shop application object to get the job done.

"hey I got a framework" but react itself does not cover the requirements for being one and even react can be a lib to extend functionality inside another framework.

And again you're talking about an "application framework".

send an email to React team with your complains to see if they change its own description

After 8 years they are not going to change anything.

Best guess: "JavaScript library" is being treated as a marketing (propaganda) term:

  • So that people don't have false expectations of a "batteries included" solution like Angular.
  • So that people buy into the whole "so simple, React can be learned in a weekend" meme.

You can start here for example.

That article is irrelevant as it commits the same mistake of equating "framework" with "application framework" (perhaps even a case of false equivalence) as the author does not convey an understanding of the fundamental characteristics of a general framework (vs library) that were established long before React was authored.

The distinction is important because IoC used by frameworks to run user code impacts how you structure an application - often not in a good way. If you're comfortable re-writing your client-side apps every two years or so or start to look for another job then you won't have to bear the consequences of not countering the bias that React can introduce into an application (i.e. React is opinionated - in its own way).

Thread Thread
 
joelbonetr profile image
JoelBonetR 🥇 • Edited

Yeah ok, watever. TLDR.
All people is wrong but you.
This is my last answer to this thread, sincerely, you make all of us loosing time from a biased pov or misunderstanding of concepts.

I let you this link from a person I appreciate within the industry for his way of explaining things describing just that concepts.

Thread Thread
 
peerreynders profile image
peerreynders

Please listen to your own advice.

Thread Thread
 
fabiorizzelloomnia profile image
fabio-rizzello-omnia

Best guess: "JavaScript library" is being treated as a marketing (propaganda) term:
So that people don't have false expectations of a "batteries included" solution like Angular.
So that people buy into the whole "so simple, React can be learned in a weekend" meme.

Exactly