Why We Moved to React
tech.instacart.com
tech.instacart.com
That said, React is just a part of it, and some flows are counter-intuitive in React. This must be said because it is true... that said, I find that React is far better, all around than most of the other options I've used, and I've been building web apps for two decades now.
I'm currently working on supporting an Angular 1.x app, have a proof of concept built in Redux+React, and another app I've been instructed to write in Angular 2. I've also built a couple of SPAs using Backbone. In the end the Redux flow has meant less code as features are added, and I'm working towards writing my Angular 2 app with that in mind. Modern React takes a lot of tooling setup to get started (or starting with someone's existing boilerplate), but the shear amount of boilerplate code that you have to write with Angular2 is just unnerving. The DI model is awkward, and I'm not enjoying it at all...
The Redux+React proof of concept is for half the functionality of the Angular 1.x app, I'm pushing for the change in the next version... with about 1/3 the functionality, the code is 1/10th the size, and there's a lot less complexity... A single state tree, in the end is easier to reason with, even if you're only looking at part of it. It's much easier to deal with, even with scale than trying to add more message channels in an application between components. Getting used to separating actions via a single dispatcher, and the resulting state changes takes getting used to... but so much easier in the end.
Yeah, that's the usual 80/20 rule at play.
1. Elm. I was just about to throw away the idea of Flux in a web app till I saw TodoMVC implemented in Elm. In Elm everything is immutable, and as a functional language, it has a lot of helpful syntax to help you deal with immutability. Shoehorning immutability into Javascript seems to require a lot of scaffolding by comparison.
2. MobX, it's been mentioned elsewhere but I can't help but sing its praises. Writing in MobX means that using controllers/dispatchers/actions/supervisors or another form of managing dataflow returns to being an architectural concern you can pattern to your application's needs, rather than being something that's required by default for anything more than a Todo app.
https://reagent-project.github.io
I decided to use it for a small client for a chat server my company runs. The initial environment setup on OS X wasn't the smoothest, but once I got that taken care of the actual development was very pleasing and quick. You need to know just a few core concepts and then you can more or less replicate the common patterns you use in React - application state, component properties, local component state, initial values for local state, etc.
Along with that, you get immutable data structures and the benefits of the Google Closure Compiler out of the box. Give it a shot!
https://github.com/hoplon/hoplon
It requires a certain shift in thinking when coming from pretty much any other framework. However, it avoids all of the unnecessary complexities of React by exposing the DOM elements directly as functions. The mindshare behind it might be low compared to Om or Reagent, but the people that are using it are pretty active at Clojurians slack channel #hoplon and on IRC (freenode, #hoplon). It's also FRP-based and pretty efficient. Highly recommend!
A simple, almost ToDo-like form quickly grew to 7 files, averaging 100 SLOC each, with a air-filled boilerplate-feeling classes (yet not lacking works-by-convention magic) that juggle data through those render -> onClick={e => this.onItemAdd(e)} -> onItemAdd -> addItem -> update -> UpdatePromise -> handleUpdateItems -> render loops.
Sure, everything's logical but that feels like I'm deeply stuck in the wheel of Samsara, writing code for its own sake and not attaining any Enlightenment. ;)
you seem to have fallen prey to overengineered examples.
that example should be
>> render -> onClick={e => this.onItemAdd(e)}
thats it, data change should re render the tree.
A simple, almost ToDo-like
You can do things like writing sever-syced component,mixin ect .You have state and props, and the React tree diffing algorithm attempts to make some minimal set of changes that preserves state. However this algorithm is a heuristic, and so it's possible to hit a case where your component gets a different component's state.
For example, say there's a text field which has keyboard focus. Another text field is added above it: the keyboard focus should stay in the bottom text field. But React has no notion of identity and doesn't know whether the top or bottom text field is new. All it sees is a diff from one text field to two, and who knows which one will get focus!
React's answer to this is to introduce identity by assigning each component a key, and that works. But this is reactive: I notice a bug, and fix that case by assigning a key, but still most elements do not have a key and it is not reasonable to add one. I'm stuck hoping that the opaque tree-diffing heuristic is correct enough for my case.
How do other React users handle this? How do you go from "seems to work" to "I am certain React's tree diff will assign the right state to the right components in all cases?"
We try to keep the structure of the html so that wrappers generally keep different UI components separate from each other. In other cases, like in the example in the blog post, we just use the index from the .map() loop to add a key to every element we know will need one. React should also warn you when this is an issue.
Doing this could hide weird bugs. Let's say we render a list of posts with "remove" button for each one. The user clicks on "remove" button, we modify the underlying this.state.posts. And on next re-render removed post key would be assigned to the next post! The next post could inherit just-deleted post handlers, for example.
It's much better to use unique keys like database ids.
If your list is totally static, an index will do the job. However, we usually end up appending something like an id from the db since almost nothing on Instacart is static.
Even the simplest elements like <p> have state and meaningful identity, like their text selection range.
But... the other problem with _.uniqueId is that in an isomorphic setup your server will just keep counting up and up while your client will start from 0 on every page load. So the first time you reinflate React on the client side the checksums won't match and will cause a full-page re-render.
Basically, no matter where in the array a value is, it should always have the same key.
Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `YourComponent`. See https://fb.me/react-warning-keys for more information.
* Supply the key to the top level list item component. Do NOT have the list item component define its own key in its render method. That is not how it works
* Don't use the array index for the key. Use something that's unique to the VALUE.
* Don't use _.uniqueId() or similar in any render loop. It will trigger a re-render every time, even if your underlying data has not changed.
* If you use _.uniqueId() outside of a render loop, for example to set a temp ID on a brand new data model (what Backbone does by default), and you have an isomorphic setup, make sure that your client and server counters stay in sync. The server version of _.uniqueId() will just keep counting up forever unless you do something about it.
You really need to try to find something unique (or unique enough) about the data itself. In the case of strings, use the string as the key. If the case of objects, if you really HAVE to, if there is nothing else that could possibly work right, you might get desperate and JSON.stringify them to make the key. Hopefully it doesn't come to that but it's still often better than alternatives that force full DOM reconciliation on the whole list.
I used jQuery to build 4k loc applications. It's a fucking blast when you are just wiring up the template and watching the UI come alive...to me that was the power of jQuery. No need to think, just go and make everything stick like glue.
Angular.js was also right in that regard....add annotation to HTML. but this shit doesn't scale when application grows.
I'm still frustrated that I can't write shit in jQuery anymore because HN have collectively ruled against it and I guess at 4k loc it has become very hairy.
But I still argue if your needs are pretty small, like make a small widget app that has two buttons and makes ajax request to an endpoint, no other frontend framework can even touch jQuery in this territory....
In fact the overhead of having to think about states, structures, components organized in hierarchy...this shit adds to my stress and I can't experiment fast...but then also was the stress from not being able to add new features because the jQuery app grew in complexity....
difficult times gentlemen difficult times. I've been holding on to jQuery since 2009...maybe it's time to venture out entirely with React.js? Or should I crawl back to the comfortable cave that is jQuery where I can make anything very quickly.
If you have a small javascript feature to implement, just write in jQuery.
Disclaimer: mine, and has about another month to 1.0 stability.
When I started venturing beyond jQuery, things like Knockout were a god send for simplifying data-binding (and they are still around).
React is fine, but it's really no silver bullet
have yet to use it but seems like that handles data binding....
Backbone also has a dependency on jQuery, which isn't very useful in React apps since mutatuing the DOM (one of jQuery's main purposes) is a no no. So most of the Backbone library isn't very useful to us anymore. I do still really enjoy the backbone way of fetching and saving models, especially in a Rails context. But I think we can get those features in other ways.
I use jQuery for animations and also for non-crud pixel-level DOM manipulations as in the graph shown in the home page: https://conceptcoaster.com/course/python-tutorial/ In the graph, I need to dynamically calculate height of certain elements based on the height of others. The height cannot be predicted in advance. Can React work for such cases too?
Trying to figure out a way to implement this with React + React Router...
It's not a true dependency but it's a default companion and optional dependency (see Backbone.$).
Source: http://backbonejs.org
This adds more ceremony around changing the state but in my experience (I’m biased: I wrote Redux) makes such changes easier to debug and test.
Every change comes as an action that the whole reducer tree can handle, so changes are predictable and reproducible if you record actions. You can change how actions are handled without changing the components dispatching them. A good example is how your components can emit SHOW_NOTIFICATION action but you can refactor your reducers from allowing only a single notification at the time to keeping a stack of notifications, without changing any of the components emitting them. This is what separating actions from state changes gives you.
You can log every action and see the entire state tree before and after the action. This, in my experience, makes it easier to fix incorrect mutations spanning across multiple entities. If the user clicks a button and the state is updated, and then a network response comes, and the state is updated again, you can log diffs between the state changes and have a clear picture of everything that’s happened. In fact Redux DevTools even provide a UI for that, e.g. https://github.com/alexkuz/redux-devtools-inspector.
One feedback I hear particularly often about Redux is that people who never wrote unit tests for front-end apps started writing them because it is just so easy to test reducers. You don’t need to mock any dependencies or simulate AJAX requests because any new data (whether local or remote) comes in the form of actions. So you can just call the reducer with a state and an action, and assert that its output matches what you expect.
With a single state tree I found it easier to ensure that all state is normalized and you don’t have duplicate data. In Backbone, it is encouraged that models are instantiated as you parse the request which makes it non-trivial to normalize them and merge the changes. In Redux, any merging is going to be explicit, and you can always inspect the single state tree to make sure the structure is normalized and matches what you expect it to be.
By contrast, in Backbone, models are active records so user.followUser(anotherUser) will set() a few flags on itself, fire off an async request, set() fields on another model, then possibly revert if the request failed. This is pretty hard to do consistently because there is no central point to mutations. You also have to build some sort of cache and entity resolve mechanism to make sure you don’t have duplicate out-of-sync models describing the same data.
Finally, in Redux mutations are forbidden so it is easy for the views to bail out of reconciliation if the corresponding state fields have not changed. In my experience, Backbone doesn’t make such optimizations easy because it was designed with completely mutability in mind.
So Redux, in a way, is similar to Backbone, but also is very different.
Backbone is really just an event bus, some smart wrapper logic around updating an object and an array, and a nicer setup syntax for jQuery event handlers for a particular element tree. People have then built addons that handle relational models, derived data, view lifecycles, and so on.
Redux is just putting all/most your data in a single "model", making sure all writes happen explicitly and immutably, and firing a single "change"-like event. From there people have built various ways of organizing side effects, listening for specific changes, and hooking into other libraries.
So, both simple libraries that form the basis for an ecosystem, and let you pick-and-choose the pieces that you specifically need.
P.S.I actually recently watched your Redux videos. Very nice!
I think it makes a difference. When you work with a Backbone model, you directly modify it:
model.set('completed', true);
When the logic changes, you need to change the call sites to call a model method or several model methods.On the other hand, with Redux the view specifies what it wants to happen and not how:
dispatch({ type: 'TOGGLE_TODO', id })
When you need to change how the whole state tree responds to that change you don’t need to change the components. This is the difference.* it supports set operations, `model(‘fieldName’, newValue)`, like Backbone and unlike Redux, which trigger only the necessary update actions in the (implicitly built) dependency graph. set is idempotent, even if your computed properties have side effects
* it has .on() method
* "You can log every action and see the entire state tree before and after the action.”. In freak, too:
const model = freak(statePOJO);
const history = [];
model.on(‘change’, prop => {
// change is called exactly once per mutation
history.push({...model.values});
});
freak’s README is a literal test suite, consisting of state changes and assertions.Probably it's a good idea to add 'beforeChange' event, to make it possible to cancel a mutation.
* it's currently implemented internally using mutable data structure, but this is implementation detail and can be changed to immutable data in the future, allowing simply `history.push(model.values)`
I strongly dislike the JSX syntax as well. Its messy, and difficult to read. I would like my to write my components as dom nodes, like with Vue.js, Riot. The way that react.js handles css, is also messy. I would rather just defined a <style> tag like in Vue.js.
However, newer React and Babel versions no longer compile JSX to React.DOM methods as the article shows, but other methods. Example for Babel: https://babeljs.io/repl/#?experimental=false&evaluate=true&l...
I've read quite a few criticism of JSX but "difficult to read" is a first. It's not significantly different than any templating system out there (eg, ERB). It's just XML with interpolated code, what's confusing about it?
In my opinion the confusing part is mostly the fact that taking a markup language and embedding it into a scripting language is really awkward. You have two completely different types of syntax not only existing together but working together.
Also I've worked on multiple teams where designers will re-style and even change the markup of pages but trying to get non-developers to do this with JSX is just painful.
I find HTML and the DOM API awkward at times but since that's the final state I just prefer to work with that.
Firstly: context switching is an inevitable inconvenience, but in JSX you're context-switching line by line between two radically different syntaxes.
Secondly: switching into what? It's not HTML (Angular templates, for instance, are not going to win any beauty contests, but they are technically valid HTML). XML? No, not that either. So ... something that looks kinda like HTML/XML, but which isn't really. It's perfectly legitimate to sacrifice aesthetic elegance for the sake of adhering to well-understood standards. But if you're not going to adhere to that, then why pick something that is merely similarly ugly? I don't get it.
Thirdly: templating/view layers always face a trade-off - either they are embedded within the host language, or they use an external DSL which is parsed/compiled by the host language. The trade-off is: better change of 'correctness' and cleaner interop with the rest of the language if it's an internal DSL; on the other hand, with eternal DSLs, at least the possibility that non-engineers will be able to work on things. With JSX, you end up grafting an 'internal' DSL simply by adding a whole pile of syntax to the core language. You don't have the advantages of the separate template language, and you lose some of the advantages of the other by requiring a whole pile of extra tools. JSX is an attempt not to choose, in a situation where compromise is basically impossible. Hence its extreme awkwardness - just like E4X before it.
React has done some good things: it's put performance on everyone's agenda in a big way (Hallelujah!), and it has acted as a testbed for interesting front-end architectures. JSX, however, I feel is a serious mistake. I actually enjoy writing React code through Reagent or similar, but in native JS and especially JSX, it just feels awful. I just don't want that in my editor window.
Every programming languages has multiple syntax's to learn. That's just like saying switching from array literals to hash literals is an inconvenient context switch, or from strings to comments.
React goes out of its way to make it look like you're working with the real DOM, but in a different way. Take the event system for example: https://facebook.github.io/react/docs/events.html
In that sense its even closer to the standards than Angular is - it still uses events instead of databinding.
> the possibility that non-engineers will be able to work on things
Its highly suspicious that it was ever possible because of tight coupling between template and its data. Just look at an Angular controller and view. Tell me that two different people can work on that in parallel, one on the JS part, the other on the HTML part. Its impossible.
At best you can have a designer work on the HTML part first, then a programmer can import it (a fancy word for copy paste + add all the dynamic behaviour), then perhaps the designer can do incremental design-related fixes but might need to consult the programmer regarding the data. The programmer can also do HTML fixes but might need to consult the designer regarding how they would look.
Lets see if that workflow works with JSX:
* copy-paste: check
* add dynamic behaviour: check.
* tweak and maintain the design: provisionary check:
If the designer really can't handle the surrounding JS, (although given what you are saying it sounds more like the programmer cannot handle the sprinkled HTML), you can move the render function in a separate file: module.exports = function() { return (
// JSX goes here.
); };
Problem solved.Anyways, this is just staying inside the box with old aesthetic sensibilities developed from a bygone dark ages era. React is a peek at what HTML and JS could be, if only they actually worked together. Its also a snide remark * implying: "Hey WWW, you're doing a crappy job at supporting web applications. Let me show you how its done"
* not saying its intentionally snide, just that it might come off that way
<p>
Hello and welcome to our fancy site, where you
can do all kinds of cool things.
</p>
In JSX, that text will become "...where youcan do all..." and the recommended solution is to type {' '}
to insert a literal whitespace. [Edit: See spicyj's response; I was wrong about this, but the behavior is different from HTML in other cases.]That, plus the way JSX confuses the hell out of language modes—Emacs, GitHub's rendering—makes me want to stop using JSX. I just don't enjoy using it, and I really do enjoy creating DOM elements with normal JavaScript syntax.
But like so many other things people argue about... it's just preference, and ultimately pretty insignificant.
<p>
Hello, etc etc, please
<a href="#my-neat-anchor">click here</a>
to continue.
</p> <li>Hello</li>
<li>World</li>
<li>!!!</li>
You now have text nodes containing a space in between the <li> elements. These will subtly affect how the elements are rendered. In HTML, if you want to get rid of those text nodes, you have to write the elements on one line: <li>Hello</li><li>World</li><li>!!!</li>
Or use float: left|right styles to push the text nodes out of the way. Both are ugly solutions. With JSX, I don't have to think about that.I've never even ran into your issue because I use React for web app development and so use translation strings (i.e. function calls) for pretty much all user-visible text. If you ask me, the trade-off React chooses here is adequate.
On a second thought, how do you access the Contact form on a website you can't even load? :)
Where possible you can use composability, extracting common function into a subcomponent, but this doesn't always make for neater code.
Functions:
add(1,multiply(2,3))
HTML: <div>foo <span>bar</span> </div>
React: <Container> <Header>foo</Header> <p>content</p> </Container>Composition is a useful tool, and so is writing functions like this, but they are two different ideas.
That's trivial to fix...
But you could also extract the code logic in a product module, and reuse it in both components, which can even be pure functions.
Lately I've been realizing how easy it is to fall into the "abstraction trap". It's exactly your situation: I have a Thing. I need a new Thing that's slightly different, but I don't want to copy all the code! That's not DRY! It's paralyzing.
So instead of duplicating code I spend time trying to tweak Thing, passing in parameters, adding special rendering cases, and finally it works as Thing and a smaller Thing2. But it's a mess, and it's not factored well, and it'll be a nightmare when Thing3 comes along.
Check out this article from the other day: http://programmingisterrible.com/post/139222674273/write-cod...
In line with his idea of copy-pasting code, I think that's the way to go: copy all the code from Product, paste it into ProductThumbnail, and make it work. THEN refactor it, and pull out reusable bits... or compose the two somehow... etc.
I normally go even a bit further (certainly on the frontend) and leave duplication until I wrote something 3 or 4 times (or until it has stayed there for a little while). This ensures that when I do write my abstracted component I'm actually making sure it is something that can, at least within that app, be re-used.
I do re-use React components between different projects but am also using the same Bootstrap theme so this makes a lot of components really easy to re-use.
[1] https://github.com/facebook/react/wiki/Sites-Using-React
[2] http://trends.builtwith.com/javascript/javascript-library
It would require running either V8 to render on the server behind whatever language your backend is already written in, or calling node to serve your backend, relegating your existing backend to an API (and tying the backend rendering to your API along with the Frontend to use the same API isn't simple either).
I also think jQuery and other libraries with large usage are kind of Swiss army knives, so more people have more use for them.
I do believe over time React will become as pervasive as jQuery. Or possibly even the DOM api will eventually allow a similar style of building things natively. This seems to be happening to jQuery now :)
I think it'd be interesting for us to do another post in the future about how we measure and improve performance within our React apps. There aren't a ton of articles about this with relation to Bakcbone, it seems.
Thanks for giving it a read!
We've also at times converted backbone models to simple objects at the parent level and passed them down that way. Keeps things simpler, but we lose some of the niceties of the backbone model api. Once the models are objects, you can use componentShouldUpdate pretty defensively if you need.
We've also used throttled and debounced functions for anything which gets hit very heavily.
I'd be very interested in a follow-up in a year, once it's grown to the size of the backbone app it's replacing, and been battle-tested (in prod and in development)
We're still somewhat tangled in with Backbone, but it's been a great success internally. Performance-wise, development speed-wise and also developer happiness-wise we haven't hit too many snags.
"Employer will also accept a Bachelor’s degree or foreign equivalent in Computer Science, Computer Engineering, Information Technology, or related technical field and 5 years of progressive, post-baccalaureate experience in a related field."
We don't require a Masters. Some engineers have one (or PhD even) but that's much less important than being a great engineer.
Is there one 'popular Flux library'? Perhaps they meant redux? No other mention of it in the article.
https://github.com/acdlite/flummox
https://facebook.github.io/flux/
https://github.com/reflux/refluxjs
https://github.com/reactjs/redux
Each of these appear popular in their own right. Given they mentioned Flux, it probably is the actual Flux library.
Thanks for the post!
Then, you can massively auto-format JavaScript, use great tools that inference type information from documentation, etc... but with VomitScript, you are pretty much on your own. In fact using an advanced editor and nano will probably make no difference.
"Duh but I want to type less"... NOBODOY CARES about you typing less. If you care about typing less use templates in your editor and autocomplete.
"And it will never be known what acts of cowardice have been motivated by the fear of looking insufficiently progressive."
becomes more and more relevant to the tech world.
We are managing a few lists. How is this so complicated?
maybe React is better suited for the experienced who knows how to bootstrap all the components? I'm interested in learning React _after_ I get more familiar with the javascript-ecosystem, and it seems to start with angularjs will be a good approach?
We do have a couple side apps internally using React Router. We've liked it so far, but it's a pretty basic implementation.
You'll also need to worry about how you run BDD tests for specifications and scenarios. How can this be achieved in React as you write test suites for user stories and non-UI acceptance tests? How will this impact your continuous delivery/integration systems as well? You'll have to rewrite all your test suites into Jest, right?
There are architectural trade-offs for sure. Can you definitely say you've performed a thorough analysis before making this decision? There's a difference between having a clear strategy to move from one tech to another and knowing that the migration will not just bury you into a deeper whole than the one you think you're escaping.
http://aurelia.io/ is based on webcomponents (MVVM), ES6, and current web standards. It's amazingly simple and good architects can use their own structural patterns to create code that can actually scale with the product. DDD and BDD methodologies mesh perfectly into the development workflow, especially with Agile product development.
I wish you well, but I really think React is a short sell with dire consequences.
<h1>${router.title}</h1>
<ul class="nav navbar-nav">
<li repeat.for="row of router.navigation" class="${row.isActive ? 'active' : ''}">
<a href.bind="row.href">${row.title}</a>
</li>
</ul>
Which is almost identical in JSX: <h1>{router.title}</h1>
<ul className="nav navbar-nav">
{router.navigation.map(row => (
<li className={row.isActive ? 'active' : ''}>
<a href={row.href}>{row.title}</a>
</li>
))}
</ul>
For loops and map functions aren't necessarily business logic, but they are view logic (and you'll see them in any sort of tempting or view system). React actually makes it very bad to include any substantial business logic into your templates as the render function is called many many times potentially whenever your data changes, so you want to include very minimal stuff in there.> You'll also need to worry about how you run BDD tests for specifications and scenarios. How can this be achieved in React as you write test suites for user stories and non-UI acceptance tests? How will this impact your continuous delivery/integration systems as well? You'll have to rewrite all your test suites into Jest, right?
Exactly the same! At the end of the day, React is just Javascript. You still have your models in their own classes or functions, with your own API helper methods. How you write that doesn't change - no need for Jest. We're testing our entire app - including templates/views - using Mocha (and we're about to run tests in Karma in real browsers pretty soon).
This isn't the first time people have fallen prey to embedding HTML as a string into JS to write the DOM. 5/10/15 years ago, if we saw this, devs would just shake our heads. If anything React is an old hack, an anti-pattern brought forward again.
I misspoke about views in business logic, as you said, it is the controller logic, which should be decoupled from the view itself as well. The naive example of converting a webcomponent to a JSX component may look similar, but more complex components will only require greater complexity for the render() method to handle.
I understand your rationalization, but the crux of the arguments here are concerned with the anti-pattern React introduces and why developers who've come across this before have seen this as technical debt. The arguments for React are a matter of opinion, wherein the arguments against it are based on the practical principles for programming UIs, principles have been forged to be tried and true since the 70's.
I personally favor standards, such as webcomponents and OO programming for modules. I understand that this may not seem popular at this point and time, but 20 years of dev experience has taught me otherwise.
const ProgressMeter = ({ className, percentage }) => {
const meterStyle = {
width: `${Math.round(Math.min(Math.max(percentage, 0), 1) * 100)}%`,
};
return (
<div className={cx('root', className)}>
<div className={cx('meter')} style={meterStyle}/>
</div>
);
};I'm not quite sure what you mean by this.
Anyway, I can't help but think that the distaste of the way React does stuff is due to first impressions and not actually using it in a meaningful way. I get where you're coming from - when I first saw React I thought the JSX was a terrible idea, raising many of the same concerns you have. I'm not sure what your experience is with it, but I definitely didn't like the syntax at first. Also, although we are talking about react specifically, usually you'll be using other libraries along side to it handle the other non-viewy type stuff.
But then I actually used it, and lead a reasonably sized team to create a non-trivial web app with it. People who have been programming since before I was born, and people who learnt React for this project. Not all of them love it, but everyone is very productive with it and we all see the benefits it brings and we haven't been burned by some 'anti pattern'.
Traditional programming common sense still applies here: bad developers are going to write bad code. When something gets too large, take another look at the problem and perhaps break it down into sub functions. If you're repeating thinks, create a common module for it. Nothing really revolutionary about that.
I'm not convinced there's no one working on or with React who's seen the pain of poor separation of concerns. There are lots of smart people working on React, both at Facebook and in the community, who are just as aware of the programming. "principles [that] have been forged to be tried and true since the 70's"
Additionally, the Aurelis example we both mentioned isn't a webcompoent. It's as much of a web standard as React is.
I am not arguing about JSX syntax, but rather the principle behind it. How would I safely refactor a css class across hundreds of components in a safe way and not by find/replace? An IDE such as WebStorm actually tracks CSS classes by their reference in other HTML/CSS files and this includes CSS preprocessors. I know it's a safe bet to run the renaming, although I always preview the changes beforehand.
I'm a reasonable developer, but this is an anti-pattern that has been eschewed voraciously over the years. Your appeal to the intelligence of React's devs is an informal fallacy and doesn't change this fact.
I am not trying to be dogmatic here. Yes, breaking the 'rules' when it is warranted is perfectly fine. My argument here is that in this case, this anti-pattern isn't warranted and will be very expensive work with as the product grows. I am advocating standards and best practices. React sidesteps both for an unnecessary reason. It works, it's pretty awesome how fast it is, but it cannot scale with a product's lifecycle.
Web components keep the HTML in the DOM and are being officially adopted as a standard. They can be polyfilled with a lib from http://webcomponents.org/. Aurelia, although it is a framework, is extremely lightweight and greatly simplifies the use of web components. Polymer isn't as elegant, but it clearly demonstrates the idea of dynamic reuse. There are other alternative libs as well.
As an aside, ES6 is now standard and with Babel. Javascript is now closer to ECMA, as it was intended to be.
I think I've made my argument as clear as I can, thank you for a great (and polite) discussion. It has actually been helpful for me to voice my opinion and get a better understanding of the support behind React. Again, it's impressive how fast it is over other libs such as jQuery, but jQuery's always been bloated and is near the end of its usefulness. However that point doesn't detract from the very cool things that React can do in the right hands. I wish I could bet on it, but to me it's the wrong horse in the race.
As for testing, you can do testing a lot of different ways, including BDD or DDD (I'm using a fair amount of DDD in the project I'm working on). But other than being a bit easier to test than many competing techs, there's nothing special about testing React code. And no, basically no one outside of Facebook is using Jest; it's a terrible testing tool. (I don't get the feeling you've spent much time writing or learning React? At any rate you seem to have some odd ideas about testing and React.)
Aurelia is great, but I think you're vastly overestimating the differences between an idiomatic Aurelia-based project and an idiomatic React-based project, and underestimating the flexibility which React enables.
It sounds like your experience with React has been limited and based on just looking at things.
As with anything else you will have some "view logic" (example: to render "1 item", "2 items") but not necessarily any "business logic".
I'm not going to convince you in a comment reply but if you spend a significant amount of time with React you'll see.