54 comments

[ 0.23 ms ] story [ 37.1 ms ] thread
I'm a bit surprised to see this on a site such as infoq, and being written by a developer from Thoughtworks.

If you have a 'complex project' you are going to need more than just ReactJS. It's like saying Handlebars templating is no good for large projects.

The reusability of components in a large project, and specifically the issues the author points out about interactivity between components, isn't supposed to be done in react, you're supposed to have a data (store) layer which manages the state of your components. This means the component itself is essentially just an template for your output.

I keep talking to people that put too much business logic in their components and then complain about react's unmaintainability as the project begins to have problems. Most of the time is because of poor component design and lack of a clear state/data management
I am surprised that is still a thing given that React + Redux is very popular. I would expect anyone delving in React to at least be aware of it.
Most of this article seems to be complaints about using Javascript, a dynamically-typed and interpreted language, vs using a statically typed compiled language like Scala. The author also seems to dislike the idea of client-side logic and data fetching, as opposed to server-driven.

A number of the comments about React are very overstated or overblown. For example:

> Since the two versions of virtual DOMs are mutually independent, the React framework has no idea about what is going on in data sources, randomly guessing processing operations depending on just these two DOMs. This kind of algorithm is extremely slow and inaccurate.

In reality, unless the component tree is dramatically changed (such as changing to an entirely different screen), the new VDOM contents are likely to be almost identical to the previous contents. React makes a number of educated assumptions about the structure of a VDOM tree to efficiently diff the changes. That does take processing time, but saying it is "slow and inaccurate" is just silly.

Ultimately, this article seems to be mostly about bashing React and trying to sell the author's Scala HTML bindings library instead.

(comment deleted)
Some of these grievances might be better titled "things that thew me off when learning React".

I'm not quite sure how using "className" vs "class" materially affects a complex project.

propTypes are pretty shallow in terms of checking, but I've seen them more as something third party components should provide as metadata/documentation rather than replacing a type system. Large project should rely on Flow or TypeScript if they're worried about typings.

I'm not sure I follow the complaints against asychronicity? Maybe when dealing with improperly complex components it becomes tricky and that I think takes experience to get a feel for.

Additionally, if we're comparing what appears to me to be a synchronous two way binding pattern to React, I think it's really just a matter of choosing the wrong technology for a given preference. React and the omnidirectional data flow pattern are directly opposed to that.

>I'm not sure I follow the complaints against asychronicity? Maybe when dealing with improperly complex components it becomes tricky and that I think takes experience to get a feel for

I found this argument pretty confusing at first too. I think since the author is familiar with Scala he may be used to the Actor style of async programming used heavily in the Akka framework that abstracts most of the hard to understand control flow away from the programmer (http://doc.akka.io/docs/akka/2.4/scala/actors.html).

It's a valid complaint, but as long as Javascript is the only choice for developing on the web we don't really have an alternative.

Whoops, missed the edit window. s/omni/uni
I don't think the author of this article really understands what React is and what it is not. They repeat several times that React is a framework - it is not. React is a library, one which you can use to render components and build interfaces. It doesn't claim to be a Framework for handling data, and making comparisons between the number of lines required to write tiny TODO applications isn't exactly convincing when the argument is that you shouldn't use React for complex projects.

The author writes off solutions such as Redux which are designed to solve nearly all of the "problems" the author assigns to React because they add extra layers to the application, however in reality, separating your data and your views is EXACTLY the point - that's what helps to make complex applications manageable.

The article is really an advertisement for the authors own framework Binding.scala, rather than a critical look at React.

If you have to architect your project around the use of this "library" then it smells a lot more like a framework.
You don't architecture you project around React - you simply fit react in wherever you want to render the UI. React has a very small API, most of which are simple lifecycle methods for dealing with changes in the state of a component [1].

You tell React that you'd like to Render component X inside DOM element Y, and that's really all React does. There's no architecturing your project around React.

[1] https://facebook.github.io/react/docs/react-component.html

You will want an application architecture if you're writing a complex project with any view library. React isn't special in this regard.
Agreed. It's only special because some people want to call it a library instead of a framework.
That's because it _is_ a library. If you compare it to something like Ember, it's pretty obvious that's what it is.
The architecture of any web application will be affected by your view layer, whether it is react, custom built, or any thing else.

Yes, if use react, you need an architecture compatible with the reactive paradigm.

Last time I had the library vs framework argument (1996), I concluded with this definition:

You call a library.

A framework calls you.

I don't know React, so can't say which it is.

Yeah, I would agree that in that sense, React is a framework. You call ReactDOM.render(), but from there it instantiates your components and calls their lifecycle methods as appropriate.

On the flip side, it's nowhere near as all-encompassing as Angular or Ember. No built-in AJAX handling, no complex data model manipulations, no preferred project architecture. So in that sense, it's much closer to the library side of things.

> They repeat several times that React is a framework - it is not.

People[1] who were there when it started seem to be OK with calling it framework:

http://queue.acm.org/detail.cfm?id=2994373

[1]Pete Hunt, who at the time was an engineering manager at Instagram as well as one of the more prominent members of Facebook's React core team, is willing to shed some light on React's beginnings.

Also helping to tell the story is Paul O'Shannessy, one of the first engineers at Facebook to be dedicated to React full time.

> The article is really an advertisement for the authors own framework Binding.scala, rather than a critical look at React.

I'm not sure how I feel about this. One one hand he's clearly biased. On the other hand, for a new project if he doesn't promote it no one will. It's important to market your product even if that product is an open source project.

Although if this was a serious journal or newspaper there would be a very clear disclaimer somewhere. Which is lacking in this article.

I disagree with at least one of the authors critiques:

"Issue 1: React components are difficult to reuse in complex interactive web projects.

Such a lightweight component is very handy in rendering plain and static webpages. Nonetheless, when there are interactions between one component and another, passing callback functions as parameters are inevitable. Particularly for webpages with complicated structures, we have to nest dozens of components from the inside-out, where those callback functions are passed through from parent to child components across layers and layers. The only outcome for applying React framework in complex interactive web projects is that the codebase would become too messy to maintain."

Out of the box React is relatively spartan, which is great for small projects. At scale it only really comes into its own when used in conjunction with other things such as Redux and its wonderful ecosystem of middleware.

In this kind of situation, I would advise using something like Redux and following the advice of Dan Abramov (Redux creator). He wrote a wonderful article on how to split functionality between components and containers:

https://medium.com/@dan_abramov/smart-and-dumb-components-7c...

I think this is a great pattern to follow for larger scale projects.

"It is well-known that React is a great tool for implementing simple interactive websites, but how does it apply on complex interactive front-end projects?"

Facebook seems like a pretty complex website to me and they are all in on React.

As to his points about the virtual DOM performance, I'd love to hear a more experienced web dev chime in on that as my area of expertise is native development.

Redux (and various projects in its ecosystem) resolves alot of the criticisms in the article. To this:

> As to his points about the virtual DOM performance, I'd love to hear a more experienced web dev chime in on that as my area of expertise is native development.

His example of an <li> with a <ul> is wrong. Setting that aside..

Depending on the operation and the browser, you can do anywhere between 2000-100000 more operations per second in a virtual DOM than in the browser DOM.

The complaint that complex render functions are wasting precious resources is valid, which is why documentation makes it very clear that these functions should be as simple as possible and produce no side effects. Remember - library, not a framework.

Additionally, it belies the question of - why are you writing a complex render in the first place. In a well-structured app, components would be reasonably small and render functions relatively simple, for varying definitions of 'relatively.' That is, you aren't doing complex number crunching in the render. When I do React perf optimization, one of the most common errors I see people make is have render functions full of complex logic and branching render paths. If you are doing that, your component can be further broken down.

Apparently Facebook is built on over 100,000 individual React components. Damn.

I agree. Redux resolves a lot of his criticisms thats why I really didn't get why the author dismissed it so quickly:

"For example, besides the four facets above, the state management problem of React is non-negligible. If we introduce a third-party library such as Redux to deal with the state, the framework would become tangled and the number of layers would increase."

Given how widely used Redux is with React I would have expected him to expand on this point some more and provide a meaningful critique. It's a shame that the other parts of his series have not yet been translated into English. Perhaps he elaborates on what he means by the above statement.

I think React is a good framework but it's not as elegant as Google's PolymerJS in my opinion. React's main strengths are its large community (which means lots of plugins and add-ons) and its native device support (React Native).

My main problem with React is that it's more complicated than it needs to be - If following an architecture like Redux, you often end up with long complex chains of reducers and components which makes the logic very hard to follow - Especially if you like to split up your code across multiple files.

There are few things worse than having 10+ files open at the same time and having to figure out which one(s) is/are the cause of your problem.

React isn't redux.
Sure, but its very widely used in conjunction with React especially in larger projects. I think its fair game for critique in that context. Also, the author of the article specifically called out Redux:

"For example, besides the four facets above, the state management problem of React is non-negligible. If we introduce a third-party library such as Redux to deal with the state, the framework would become tangled and the number of layers would increase."

I like Redux but I think the actions/reducers structure can be a little cumbersome to follow at first.

IMNSHO, Redux is a footgun, and adds so much boilerplate and code discontinuity as to negate much of it's benefit outside of colossal codebases and teams.

Instead of reasoning in one file, now you have to reason through half a dozen. Poorly set up actions/reducers will _stay_ cumbersome to follow, and aren't appropriate for every application.

However, none of it's problems are due to react.

I agree. Dan Abramov the creator of Redux has a whole article devoted to this topic:

https://medium.com/@dan_abramov/you-might-not-need-redux-be4...

A lot of the work I'm doing right now is in a reasonably complex react native app with multiple screens. In that context its worth the added boiler plate. I wouldn't use it for a one or two screen app with little shared state.

Yep, totally valid problem. For that, I use Jumpstate. One file open for state, one file for your component. Yay.
> Though Binding.scala somewhat looks like React, the mechanism hidden behind it is easier and more universal, which is completely different from React and Widok.

> Apparently, Binding.scala is more flexible and powerful. We can use Binding.scala to solve complicated issues that React cannot.

How did the author come to this conclusion?

He only complained about issues he saw in React, he didn't really compare them to how it would work in binding.scala. I'm sorry, but I find this post a badly written example of `software A is bad and therefore you should use software B, even though it is not examined critically`

*edit: formatting

The author of this article is the author of Binding.scala so presumably he is an authoritative source on it. However, not an impartial one.
This article purposefully misrepresents React in favor of the author's own framework Binding.scala, all the criticism are either superficial like class being className (which is a good thing because JSX is not HTML) or has nothing to do with React like JavaScript's dynamic typing system and handling of asynchronous updates.

He also seems to believe that React is framework when it's a library, if his knowledge of React is so shallow that he didn't even read the first sentence on the React website I can't take his opinions on it seriously.

I don't like these kinds of articles which are only thinly veiled advertisements that do not offer any thoughtful criticisms, what I would really like is to hear from someone who has actually worked on a huge project which includes React and what troubles if any they ran into.

I agree, as I read the article I got the same impression. This sentence did it in for me:

> However, after a few weeks, as I became more skilled in React

Do it for a year and a half and I'll accept your criticism. A few weeks is not enough time to claim enough expertise to be making the claims the article makes.

> The minimal reusable unit in React framework is React.Component

Wrong. And if you think the correct answer is "function" then you are wrong as well. The answer is: an Element. A pure, immutable value representing a React element. Example: const myReusableDiv = <div />;

> Developers have to manually replace class and for attributes with className and htmlFor.

So? It's just syntax. You can teach that, along value interpolation and everything that a designer might need to be able to make changes to templates, in less than five minutes to someone who only knows HTML.

> [talking about propTypes]. Yet this mechanism is full of holes.

So is JavaScript. Nothing to do with React. Scala is better, obviously. Any statically typed language is better at that. And there even are languages which are better at that than Scala.

If you are all like 'lol JS has no types, look at my fancy Scala code' then I'll smack you with my Haskell ADTs. And then somebody from the Agda or Idris camp joins and gives you a taste of dependent types.

> [how async programming is bad]

Nothing to do with React. React is just for rendering the UI. How you manage the data is entirely up to you.

> If you are all like 'lol JS has no types, look at my fancy Scala code' then I'll smack you with my Haskell ADTs.

Gave me a good chuckle... But on a serious note, at least the author is providing a programmatic solution to the problem, albeit being framed rather one-sidedly.

To be fair <div /> is a function when converted from jsx to js
<div /> is a constant. It's syntactic sugar for React.createElement("div"), which is at runtime represented as an object {type:'div', ...} and a few other fields.

typeof <div /> === "object"

I misspoke, yes it's a function call to React.createElement
> Particularly for webpages with complicated structures, we have to nest dozens of components from the inside-out, where those callback functions are passed through from parent to child components across layers and layers.

Does anyone have any tips for avoiding this extremely irritating 'props-nesting' (as I like to call it)? I'm pretty new to React, and the one thing that's bugging me about it is that in more complex UI (for example, a toolbar that independently controls a nested component), is how you can't just go through a top-level component directly; you have to go all the way up and down the chain. This gets very messy once you decide to change some of the intermediate components fundamentally.

This is one of the problems that Redux solves. If you have used it, you'll understand why - the state effectively lives at that Singleton level you are talking about, and components can opt-in to subscribe to changes in the state that they are interested in (at as granular a level as you wish).

Vanilla Redux is quite obtuse. I prefer Jumpstate, which makes it much more declarative. https://github.com/jumpsuit/jumpstate

I have built some fairly sophisticated applications in React and never pass props down more than one level. Like anything else, doing this well requires discipline. The author of the article appears to be complaining that React isn't a silver bullet.

One simple technique is using JSX spread to pass all props down the component hierarchy. Another is using a state container such as redux and using its container abstraction to inject actions that mutate app state into the components they are used in.
Yeah there is a bit of a learning curve there. I was doing the same when I first started.

It really depends on what you're trying to do, but it really comes down to storing state and data in a central location.

If it's a simple component, passing the on click callback to a child that updates the parent master state is pretty straightforward. So for example selecting an item in a list and updating the active item when a list item is clicked.

If it's a really deeply nested component though, that can get a bit harder. I've had some success passing simple string values via the context reference, which makes the values accessible to all the children.

Another pattern I've used is having a state store similar to the flux pattern using eventemitter. I'm using this pattern a lot on thebigpicture.io for the editor page. There's two main columns in the page that are very deeply nested, so I created a separate state store and individual components are able to listen to changes from different events.

Article bashing React, written by the author of the library he suggests you use instead.
Nup - none of these criticisms seem valid to me.

And a particular comment about asynchronous programming - ALL JavaScript requires async programming and you need to know how to properly handle it no matter what you are programming.

Having no experiences with it. The author calmed that is faster but the benchmark result in below chart was shown different word:

http://www.stefankrause.net/js-frameworks-benchmark5/webdriv...

Given a component that contains n elements, and you want to update k elements at a time, ReactJS requires O(n) time for virtual DOM differentiation, and Binding.scala only takes O(k) time.

As a result, Binding.scala is fast when k < n (aka partial updating), even faster than vanillajs written by a common human for some cases. Check the rows "partial update", "select row", "swap rows", "remove row" in the benchmark.

Nobody cares when it is 6ms instead of 3ms for partial updates. What is really important is how fast you can create and remove huge amount of nodes (switching pages in SPA, etc), because it is already takes a huge amount of time, and Binding.scala just adds a huge overhead to this cases.
Well, that's one way to turn people off to your new framework. Maybe something got lost in the translation? Maybe this reads better in the original language? Maybe not. But even then, as many people have already commented on, it's just plain wrong about React.
I don't know, Facebook seems like a pretty complex project and they use React.
A quick correction to the following claim:

> ... if you wanted to insert <li> on the top of a <ul> form, then the React framework would misjudge that you modified all components of <ul> and appended <li> at the end.

Yes, that will happen ... but only if you don't assign a key property to each of the `<li>`s. React uses the key prop to uniquely identify nodes that were actually changed versus ones that were just moved around among their peers. So if you're dynamically creating lists of nodes of the same tag type, you really need to be giving them a unique `key`.

Also, it's not a framework, it's a library. A framework calls your code, a library gets called by your code. With React you call `ReactDOM.render` or similar.

Every front-end engineer knows - React is a library and not a framework. From my own experience one of the best ways to see where React shines is to try out one of Clojurescript libraries, and there are plenty to choose from: Rum, Re-frame/Re-agent, Quiescent, Om.Next. React plays extremely well with immutable data-structures. Om.Next is mind-blowing awesome.
React is not good enough since it's based on JavaScript. Swapping the language to ClojureScript or ReasonML, the situation will change.