So here we see the culmination of the great Frameworks vs. Libraries divide. Frameworks alleviate the need for the type of articles like the one linked here because they eliminate choice paralysis and imposter syndrome. Everyone is worried about whether or not they're doing things The Right Way™ and so they either blaze ahead and hit the same pitfalls everyone else does (and then write blog posts to warn others) or they hold off on adopting the tech until they are shown The Right Way™ by someone else.
The truth is, libraries and frameworks both end up being equally complex to work with, precisely because the problem of building large applications is inherently difficult.
It all comes down to personal preference:
Are you the type of person who is more likely to believe you can do something better than everyone else, or are you the type who is more likely to defer to those you believe to be better than you?
Are you decisive or do you agonize over the smallest choices?
Do you feel a compelling need to understand how everything works, or are you willing to implicitly trust other people's systems?
I find it amusing that people who gravitate toward smaller libraries like Backbone.js and React.js rail against frameworks like Ember or Angular for being overly complex, heavy, and "magical", and then proceed to cobble together a Rube-Goldberg-esque system of disparate dependencies to achieve the same goals. When React first started getting popular all you read about was how simple the API was and how it was Easy to Reason About™. Fast forward to today and you need to have working knowledge of WebPack, ES6, Redux, immutable.js, Babel, and a bevy of other dependencies to be aligned with the React ecosystem's ever-evolving best practices.
The exact same thing happened with Backbone.js and it will probably happen again with the next shiny new view-model library to ride the hype train.
It's important that I point out, however, that none of this is necessarily a bad thing. Smaller libraries like React.js and Backbone.js encourage a cavalcade of innovation from which awesome things like Redux are born. But let's not pretend that this doesn't result in a heckuva lot of churn for the average developer whose job is to simply get shit done.
I agree with your argument. I have seen people say on HN that 1 hour of setup to start a project is too much. If this is the case, React + stuff is really not the right thing for you.
However, the React ecosystem is really not that complex. You can write clean, sizable apps with vanilla React.
Then you might need a state management system like Redux. Its quite easy to roll out your own that fits your project and does not have all the pluggability whistles like Redux.
All other things are really not needed for most people, and if you do, you are facing problems so large, evaluation of libraries is a small fraction of the effort.
It's more the mindset of people "I'm missing something great" that drives them crazy and into framework fatigue. (OMG server-side rendering, falcor, relay, immutable.js arrgggh)
Usually, you are missing something you don't need, otherwise you would be looking for it actively.
> Then you might need a state management system like Redux. Its quite easy to roll out your own that fits your project and does not have all the pluggability whistles like Redux.
For anyone that has the ability to pull off a project that needs seperate state management.
It's really just a days worth of looking at the original flux, redux and other implementations and figure out what's best for your team and project.
It doesn't take more energy / knowledge than to hack around patterns that don't perfectly fit your projects needs with the "everything included" frameworks.
I see it as a set of web framework construction tools. You can roll your own isomorphic web framework in two weeks, whereas ember.js and angular.js took years to build.
We build the framework that's suitable for our company. Once we got a thing going we use it for multiple projects.
You describe ES6 as some kind of exotic dependency. Actually once you get rid of ES6, the only dependencies in your list are immutable.js which is optional, and redux, which has become the well-known default.
> You describe ES6 as some kind of exotic dependency.
To the non Silicon Valley / Hacker News crowd, it certainly is. And using ES6 means you need to make a choice about which transpiler to use, which build tool to use, etc.
> Actually once you get rid of ES6, the only dependencies in your list are immutable.js which is optional, and redux, which has become the well-known default.
Well known to who, exactly? Because the "well known default" as of a few months ago was Reflux, and before that it was Flux. Oh, and there's Relay and GraphQL.
When's the "well known default" going to change again? I give it two months before everyone rushes to the next new gotta-have dependency. It's like reading Dr. Suess's The Sneetches.
You're not wrong: things do change quickly in the JavaScript world. But have you actually been following this stuff very closely?
"Flux" was never a "well-known default," because there was no single "Flux" library - only Facebook's little written guide and an implementation of the dispatcher (a small part of the overall Flux architecture).
So, there were about 500 different implementations of "Flux" - none of which I'd say were ever considered a "well-known default" (the biggest ones - Reflux, Alt, Marty, Flummox, and Fluxxor - all have roughly between 1000 - 3000 stars on GitHub).
Then, Redux came on the scene and became the first and only "well-known default". Several of the Flux libraries I just mentioned actually deprecated themselves and put up notices to use Redux instead. As of the time of this writing Redux has almost 13,000 stars on GitHub.
Relay/Falcor are really part of an entirely different thing than React; they are about replacing the traditional REST API with an entirely new paradigm.
> But have you actually been following this stuff very closely?
I have, but I'm trying to spin my comments from the perspective of the average developer. People who are passively keeping tabs on what this whole "React" thing is about are probably feeling a little uneasy about all the churn. I agree that Redux has emerged as the clear solution for data management, and I'm a huge fan. But I don't use it with React. I'm keeping my distance from that ecosystem while the dust settles and waiting to see what kind of splash Angular 2 makes.
> Relay/Falcor are really part of an entirely different thing than React; they are about replacing the traditional REST API with an entirely new paradigm.
But what app doesn't use a traditional REST API? Why wouldn't people want to use the latest hotness to come out of Facebook™ or Netflix™? It's this kind of uncertainty that keeps people off balance.
I don't know, I think you're over-characterizing this as a psychological decision. I tend to prefer libraries over frameworks for the simple reason that they're usually much quicker to learn and use (because they have a single purpose), and they don't box me into patterns I don't want or need. I wouldn't categorize that as like making me a control freak or untrusting of others design decisions, its a pretty pragmatic decision.
I don't think that's really true. Not to put words in his mouth, but the GPs assertion seems to be that library vs framework tends to not matter much other than in what it says about the individual, whereas my assertion would be that choosing small focused libraries has nothing to do with ego or imposter syndrome or whatever, I just don't want to learn a massive chunk of code if I can learn a small chunk of code and get equal value.
"I tend to prefer libraries over frameworks...they don't box me into patterns I don't want or need"
You're confident that you're able to identify what you want and need, and how to get there.
You don't need help or strong direction.
In contrast, I worry about making the naive choice, and I trust that others have thought about this a lot more than me. So I tend towards things that have built-in best practices/assumptions/guidelines, i.e. "box me in".
I think you're right, but your last paragraph is crucial.
The reason I'm doing front-end development is because I enjoy it. I'm not doing it only to 'get shit done'. And part of that enjoyment means not always having to deal too much with other people's choices, because sometimes they feel like straitjackets.
So as long as the client doesn't suffer from me making choices based on enjoyment, I'm going to use RethinkDB, React for the back-end, and roll out my own custom-built CMS if I so desire. Because I'm responsible enough to know when this is okay, and it's just hella fun to do.
But yes, when in doubt lean towards the thing that has been tried and tested over your own (possibly disastrous) sources.
But also no, the most I've learned has been by making terrible choices and having to figure things out, truly figure things out myself instead of relying on frameworks from the start.
I mean, it's not like things will explode when we fail in the front-end world, generally speaking.
It amazes me how much the software industry is like the fashion industry. Do you honestly base your technology decisions on what brand names are attached to them?
Your comment strikes me as incredibly naive. Angular was written to tackle the task of re-writing the front-end of Double-Click, by far their most profitable application. Google is putting a ton of resources into Polymer, which is powering more and more of their mission critical properties, so Angular hasn't had the benefit of being blessed by the wider organization as the one, true way of doing things. I think that's a good thing, frankly. The group-think coming out of Facebook is unnerving to say the least.
You should step outside the Hacker News bubble and do a little research into just how widespread Angular usage is. You will find that it's staggering. Google's name means a lot, even if they haven't gone all in on using Angular for everything. Don't get me wrong, I think React is a fresh new take on web development, but when I see people say "because Facebook™" it makes me cringe, hard.
What does scale have to do with front-end development? Front-end code runs on the user's machine. And regardless, it's folly to make decisions based on wanting your code to scale to Facebook level usage.
If you're a "just get shit done" person, fine, go use a framework. I've just been burned too many times.
It's not about complexity per se, it's about use cases the framework designers did not envision beforehand. Soon as you're in one of those, your goose is cooked. If the framework just does what you want and gets out of the way then great. But in my experience the pain is not worth whatever benefit a framework provides.
It's really severe, but articles from DHH and Rails itself really really help with that. I can't really put enough emphasis how greatly that has helped me.
That's what I thought, tried it. Didn't like it.
In the end, it still has to click and having separate templates for logic isn't going to cut it. React does it right, I just wish React came in a package.
Which I guess it sorta does now with Redux/Reflux.js and React-Router, etc.
I'm not a React or Angular expert, but do you really put HTML inside of your JS code? It just bothers me too much. We spent years in early web days learning that code and templates should be separate, yet here we are putting HTML inside of code, which goes against years of practice. Can anyone share their professional thoughts about this?
This is one of the main reasons why I've become so skeptical about best practice advice, especially if it doesn't come with a plain logical explanation for the reasoning behind it. Its similar to the problems with outdated laws - if we don't keep track of the reasons why a law came into use in the first place, we might miss the moment where it might not apply anymore (we wont even know, really)
While I'm not entirely sure what the original reasons were, I can see a big difference between the way, say, PHP was embedded in HTML and now JSX is embedded in JavaScript:
1. PHP was embedded in HTML, not the other way around.
2. The preprocessor basically concatenated everything as strings without caring about what DOM would end up being a result.
Because of these two reasons it was extremely hard to protect against improper injection of data into the resulting HTML. There was no way to make the preprocessor understand the different types of "placeholders" in HTML and what kind of data should be allowed within them.
In contrast, JSX embeds HTML within JS. Furthermore, JSX (pretty much) compiles to function calls, not string concatenation. This means that the engine has great degree of control over the interpretation of the data: its impossible to get malformed HTML, or for an attribute value to escape the actual attribute and so on. Which in turn eliminates the original problem that was present in PHP.
As for separation of concerns, thats still possible with JSX. We have CommonJS (or ES6) modules and we can move the render functions anywhere we want. But now its up to us to decide whether it makes sense or not.
Actually, the issue with spaghetti PHP is not (only) string concatenation; it's mostly that view logic, ___domain/business logic and database boilerplate code are intermixed in a single file.
React components only ever contain view logic, which already solves a part of the problem. Furthermore, you typically split that logic into multiple components, many of which are stateless, independent and small.
See the problem with this explanation is again, it doesn't explain the reasons why this is bad. I'm not saying the reasons don't exist - on the contrary I agree they're very much real. However I don't think "view logic, ___domain/business logic and database boilerplate code are intermixed in a single file" qualifies as a straightforward, logical explanation. It simply doesn't answer the "why" question at all.
Let me try and cover some of the reasons why. I'm sure you know about these reasons (and can probably list more), my goal is just to present an example of what I consider to be a straightforward logical explanation:
If ___domain/business logic is mixed with view logic, then it would not be possible to reuse the same logic in a different view. These changes happen more often than anticipated: for example, a PHP project that has the view logic separated from the ___domain/business logic can more easily get an API (a HTML is one view, a JSON API would be just another view)
Additionally separating database code from business logic lets you switch databases more easily or to give you multiple ways to access the data. For example, data may be directly fetched from an SQL database initially, then its determined that this is too slow and results need to be cached in Redis. If there is no separate code for the data access layer, you would need to locate every database query and make sure it queries the cache first.
So this is what qualifies as a straightforward, logical explanation for me: lets assume the opposite statement was true, then we demonstrate how this leads to a bad situation and why its bad (more bugs, more work, and so on).
Another would be doing a case study: we did X (mixed business logic and templates in this way), then when we wanted to do Y (present a different view V) we had to not only write new code (for the new view) but deal with this problem (uncouple the existing logic from the existing view). If we originally did otherwise (wrote the logic separately) this would've been the same or similar amount of work (demonstrate this) yet later we would not have to do the hairy decoupling (which took Z amount of time and caused N bugs)
I think the whole industry would do much better if we focused more on actual specific examples and case studies of problems and drawbacks of different approaches rather than giving vague descriptions of the current state and claiming its "bad". Its just not helpful at all. There is so much reinventing the wheel in our profession simply because we are not communicating knowledge effectively. Frankly, most of it reminds me of religious dogma.
That's the point that pkrumins/andreyvit are making, code where logic and presentation are mixed turn into a nightmare to maintain. And the practice is now ancient history.
I explicitly do _not_ state that it applies to React, because there's no ___domain logic in React components. (Or at least there shouldn't be. It is certainly possible to write a spaghetti component that would do everything.)
> In all fairness this is ancient history on the PHP world.
No, because PHP still work that way (hypertext pre-processor) and Yes because, PHP has frameworks that makes PHP work like other solutions (Ruby,Python,Java + frameworks), but one still need a <?php on top of a file.
And again, a lot of PHP developers despise these frameworks and question their usefulness. In theory, they are right since PHP is a template language which goal is to render text content, and separation of concerns can be easily achieve without a complex framework in the case of a web application. In practice a framework makes large codebases more maintainable, no question.
PHP is a strange beast. It's somehow rigid like Java, at least more rigid than most dynamic languages, it's a dynamic language, and a template language and it keeps on getting stuff from Java like languages (PHP 7).
It's ironic that PHP was created because its author kind of found Perl too difficult to use for web dev, then wasn't taken seriously by pros then tried to imitate Java in some ways to feel more professional and now is on part with Perl in terms of complexity, while half of the PHP community praises over engineered codebases often found in the JEE world.
My point is that PHP renders text first and foremost, writing code in PHP is "opt-in" somehow. An HTML file for instance is a valid PHP file. AFAIK an HTML file isn't a valid Ruby or Python file. You don't need to tell the interpreter to kick in at first place. But that's not the main idea I tried to convey in my comment.
Right, your comment argued that "view logic, ___domain/business logic and database boilerplate code intermixed in a single file" is not "ancient history in the PHP world". Which it is, regardless of the `<?php` tag at the top of all the files. How a source file is processed has no impact on how programmers choose to model their applications.
Theoretically no, perhaps, but practically I think there is an impact.
I can't dump html into a .rb or .js file, so I'm less likely to do so as a beginner. On the other hand, starting out with php, that seemed like the logical thing to do. Because I could.
This is a debate that has been going on since I started in the late 90ies.
You need some sort of logic in your views, no matter what system you use, i. e. loops or formatting dates.
Because people are raised on the "don't mix logic & layout" maxim, they feel dirty when they write sich logic in their usual language.
.. so they invent template languages...
... that then expand to be turing-complete and basically offer everything their primary language offered in the beginning.
So you end up with a new language to learn, which is usually clunky and ugly just for the bragging rights of "not mixing logic & views". Which is completely stupid. Views can (and almost always need) to contain some logic and the best language for that is the one you're using everywhere else.
> ... that then expand to be turing-complete and basically offer everything their primary language offered in the beginning.
then they wrote template languages on top of the template language to separate layout and logic again ( PHP vs Twig/Smarty )
so maybe we need to step back a little and figure out how to write a language that wouldn't need a different syntax for logic and layout. This family of languages exists already, but since current developers grew up with C like languages, it is not that popular.
IMHO the best compromise is direct support for XML syntax inside languages (which Javascript had at some point with E4X) because I don't think anyone will be able to make developers use LISP like languages on a wide scale. JSX, with some modifications and standardisation could also be a solution.
Calling the function hiccup.core/html on that datastructure yeilds an html string like this:
"<h2 class='selected'>Hello</h2>"
So that's great for _strings_ right? But there is an awesome library for ClojureScript called Reagent. And it uses those simple datastructures to generate react components!! I put some more examples at: http://hiccup.space
I love Clojure, but I'm tired of embedded DSLs, they're a dime a dozen. You can argue the benefits of Hiccup's syntax & s-expr all day, but it's still a different, and unpopular syntax for describing HTML.
The ability to copy snippets of HTML from web, or old code when refactoring, or from Clojure/Hiccup to another language & framework, or changes from developer tool, or familiarity for new engineers, or not having to care about what flavor of HTML is hip today is a huge productivity boost for me.
I would love to see push for template strings [1] in Clojure, it should be trivial with macros. It would only take some time for IDEs to catch up. They're good. So good they've even influenced Python 3 to add them.
It's possible to macro the above to the code below, without any language extensions. IntelliJ has powerful nested DSL introspection, it would be neat if Cursive allowed to hook into this through defui's metadata for highlighting. I was a hater of JSX until I used it. Now I hate eDSLs. :D
If (if) you already like lisp, it more feels like writing HTML with cleaner, more composable syntax. Were I working on an all-lisp team, I'd be totally happy to use it. Since I'm generally not, JSX function components seem to be the next best (or at least next-least-worst) thing.
If you are trying to make a language that doesn't need a different syntax for logic and layout, do you not end up with a templating language similar to PHP? Is this the right goal?
Yes – look for example at the .erb templates that rails uses. It's still possible to do evil stuff in those, but I actually haven't seen it in practice. The whole framework is organized in such a way that people get where their logic belongs.
The worst I've seen is a bit of confusion between models and controllers. But views are usually as clean as the Gods of MVC commanded.
Definitely agree with "the best language for that is the one you're using everywhere else"
Where I work right now, we use the newer versions of ASP.NET that come bundled with the Razor templating engine, which uses .cshtml files. You can write C# inside the files much the same way you can write JavaScript in a JSX file, it makes creating forms and such a breeze.
Big bonus is that moving from writing server-side logic to client-side logic doesn't require much of a context switch, and you can use the same objects to represent your data on both sides. If I spend all day moving between half a dozen different languages that get compiled by a dozen different tools, it can get a little exhausting.
Razor seems to have been born out of a frustration someone had with writing
return "<div>" + model.name + "</div>";
Razor is basically a DSL for C# string concatenation, where everything not escaped with an @ is a string literal to be concatenated. This means it's fairly unopinionated about structuring code. React, on the other hand, forces you to define components- ideally, pure functions from properties to JSX (which is just sugar for JS). This means composition is the default solution to everything. Razor doesn't place nearly as much emphasis on composable components, and the mechanisms it has for doing so, like helpers or calls to RenderPartial, are clunky and worlds away from the first-class component support of React.
While it's technically possible to write Razor code with a React-style focus on composition, the syntax and architecture of viewmodels/templates actively pushes you away from doing so. In my experience, most Razor ends up like a C# translation of PHP, and I think that's really the paradigm Razor inherited. Razor has been around since 2011, which significantly predates the Cambrian explosion of clientside js frameworks, so it makes sense.
Good point that it's hard to write nice and modular views with Razor; helpers and RenderPartial are pretty clunky and overall just hard to manage. I suppose it is pretty PHP-like...
> You need some sort of logic in your views, no matter what system you use, i. e. loops or formatting dates.
No you don't. Look at Wicket for how to do this right: everything is a component, the only thing[1] your templates contain is a) markup (which is 100% valid, using a namespace for the only wicket-specific part) and b) ids that indicate that a given tag will be replaced with a component. Everything else is handled by the component hierarchy in code, using proper OO polymorphism (it's also a great example of proper use of OO, with classes left with only the correct extension points, and classes or methods declared "final" if the developers don't intend to support custom ones going forwards). You end up making truly reusable components that can be very small - even something like an address input is a component defined in terms of smaller components.
I wish there were Wicket equivalents in other languages.
[1] There are a few other conveniences, but they really are minimal
When the parent says view, they're not talking about "a) markup", they're talking about the thing the user is looking at.
> b) ids that indicate that a given tag will be replaced with a component
With that in mind, your disagreement is contradicted by this statement because logic has just been described to update the view. Logic is necessary to generate a view of the data for the user.
With JSX, keeping all of this code closer together that is intrinsically tied together increases cohesion, by definition. Subjectively, this makes it easier to manage UI because one only have too check one place for all the pieces. For further exploration of this idea, check out the intro of this video on separation of concerns vs technology. [1]
On a separate point, it sounds like one must imperatively update the UI with Wicket, which is objectively more complex than what React affords, which is stateless UI. Time is removed from the equation, which also makes things easier to reason about.
> With that in mind, your disagreement is contradicted by this statement because logic has just been described to update the view. Logic is necessary to generate a view of the data for the user.
There is no logic in the "template". No looping, no branching. Only inert ids. There is logic in determining which component replaces each id, but that logic lies in the code, not the template.
> it sounds like one must imperatively update the UI with Wicket, which is objectively more complex than what React affords, which is stateless UI.
Not so. Wicket clearly separates its state into models, you write UI that depends on a model as a function of that model. It leads to a very declarative/functional style, where the only "magic" is encapsulated and explicitly managed. (You do have to declare which changes update which UI (for performance reasons), but you can make that "always re-render the whole page" if that suits your use case).
> There is no logic in the "template". No looping, no branching. Only inert ids. There is logic in determining which component replaces each id, but that logic lies in the code, not the template.
Again, changing view to mean "template" is a strawman.
> Wicket clearly separates its state into models
> You do have to declare which changes update which UI (for performance reasons),
Separating state isn't the same as no state. Also imperatively updating the UI on state changes is stateful. Which increases complexity, which for most people makes code hard to reason about.
> but you can make that "always re-render the whole page" if that suits your use case
Anything can be made to do anything, so this point is moot. If this model was trivially applied, would it lead to flickering, lower performance, losing scroll position, losing selection, or losing input focus?
> Call it what you like. The point is that clear separation between logic and markup can be done and is valuable.
You concede the original point. To your new point, saying something is valuable doesn't make it valuable. Why? It decreases cohesion, which is not good.
> Any web page that has inputs or controls is necessarily stateful - otherwise where does the input go?
If this is a serious question, it's too far off any original point to teach you unfamiliar concepts. Learn about what stateless, declaratively, & imperatively UI means so there aren't strawmans, and so you can weigh in on these discussions.
> There's nothing imperative about it. Have you looked seriously at Wicket or are you just throwing buzzwords around?
Please do not dilute conversations on here by name calling. Imperative & state are basic computer science terms... o_O
No. Your original claim was that you need to mix logic and layout. You don't.
> If this is a serious question, it's too far off any original point to teach you unfamiliar concepts. Learn about what stateless, declaratively, & imperatively UI means so there aren't strawmans, and so you can weigh in on these discussions.
It's not me who needs to learn what those words mean. Either you're just trolling, you don't understand the terms, or you don't understand wicket.
If you disagree with something I said, please disagree with it directly with reasoning, without name calling, ad hominem, or strawmans, at the exact thread. If I use terms incorrectly, correct me, and better yet, give an ironman of what I was trying to say.
To the extent that react is "stateless" (which I don't consider an accurate or useful term, because UI is inherently stateful - the meaningful distinction is whether state is managed or pervasive) so too is Wicket. That is to say, you declare what your UI looks like as a function of the model values. There is no "imperatively updating" and no increased complexity.
Good points. So, some people say, "hey, let's use a declarative language like XML." Problem is that you still need to decide what, when and how to display your model. So, we end up with tags or otherwise that are merely attempts to hide logic. <foreach>. Yeah, right.
You can go the other way...just put the logic in the controller to format data and otherwise build the model in a way that is cognizant of the view. But, then you've just "polluted" the controller with the view.
One approach at solving this is frameworks like Wicket, which (in spite of shortcomings) encourages the use of view components in a way that allows them to render a more organic model. Yes, you may write some Java to render specialized components, but you're at least using the same language and being specific about writing rendering code that is also reusable.
Exactly. I'm only able to write such powerful React components by having a full programming language (JS) in my view (the React render method). The logic-less template approach would have been crippling for me.
It is the people who LIKE putting logic in templates who want Turing-complete template languages with all the features of the host language. If you don't do much or any logic in templates, you have no reason to want that.
It sounds to me like you are arguing that because people will put logic in templates, and this leads to ugly template languages, we should just program in ugly template languages rather than doing any separation of logic from templates.
Your example actually looks like a namespace disaster about to happen with "id". Needs some prefixing and/or improved naming conventions. I'm not really how making your template have "less logic" than your example would produce a usable template language.
I suspect it's because people regard the implied foreach loop of data-scope to not count as logicless. Personally I can see the arguments both ways, and have concluded that simply ensuring I'm using the same definition of logicless as the people I'm talking to is the best answer.
Ahh, well I never claimed it was logicless. I claimed the templates were logicless, and they are. The logic is kept separate inside the processors that you bind to the template.
Except the -scope part means that the foreach-ness is indicated by the template, so people consider that to be not-logicless.
I understood your claim fine. I'm trying to explain why it might be considered false (and I did already say I consider the arguments each way basically hair splitting).
Interesting, I've never imagined an identifier could be labeled as logic. There is no need for a scope, if you mean that the outer identifier is logic. Anything could be the identifier and inside the processor you could define anything to be the outer layer. You could flip data-attr and data-scope just as easily, so I'm not sure where there could ever be an argument that those things represent logic rather than markup.
Either way, I _think_ I have a better understand of potential conflicting views. Thanks for taking the time to explain.
First, in practice what everybody turned up doing was the inverse (add programming logic inside their HTML).
So you still had mixed HTML and JS, but in a way worse way: with ad-hoc and incompatible pseudo-languages (e.g. Angular's ng-repeat etc, Knockout's template instructions, etc), spiced with "JS inside HTML attributes", with no syntax checking (a typo could blow your code in runtime) and convoluted to boot.
Now, having HTML and logic together makes sense when creating widgets/components, as you have all functionality for widget in the same place. After all in every native UI framework you have instructions to draw the widget IN your code -- not as some external additional technology. A widget's C/C++/Obj-C/Swift/Java/C# etc code encapsulates everything about creating it and showing it.
So, the better way is to have all your widget drawing depending on external (or internally stored if you must) state, happen inside the widget code itself. Not to try to manipulate a string template by sprinkling ad-hoc instructions like for-each and if-then.
And here's the better part. React doesn't really mix HTML inside JS.
JSX might look like doing such, but it's just sugar for calling Javascript functions. <div> is essentially something like: React.createElement(null, "div"); So, the "HTML" is just calls to DOM manipulation methods.
So, with React there's just JS, and it handles all the creation of the HTML code for a "component" (widget). It's also composable, so your panel is just a components embedding other components.
> After all in every native UI framework you have instructions to draw the widget IN your code -- not as some external additional technology. A widget's C/C++/Obj-C/Swift/Java/C# etc code encapsulates everything about creating it and showing it.
With the notable exception of Windows. XAML strictly enforces code and markup separation. It makes the View layer more toolable and easier to edit by designers who usually don't program.
Thats not really true - you can use some pretty convoluted converters directly into the XAML and you can have those trigger arbitrary functions in your program through one-way binding.
I agree that XAML has the most mature concept, but it cheats by introducing the MVVM pattern, which performs some data mangling that would otherwise be part of the view. Not doing this, you'll end up with custom converters etc.
MVVM is nice regarding testability, but I find it to be overkill for most applications.
That is just inside of WPF-land, though. WinForms (which is still pretty excellent for quick-and-dirty GUIs) and other GUI frameworks are more on the classical model.
Assuming that doesn't go the way of the host of other things that Microsoft has rolled out, spun their wheels on, and abandoned when it didn't take off.
XAML is a properly parsed language defined just for this purpose though, whereas HTML + framework annotations inside element attributes is way more brittle.
I think this is what everyone feels when starting with React, but the pros are much bigger (and more of them) than the cons.
the main difference between React and everything else is that React brings HTML to Javascript (and not vice versa). The result is code, that's easy to understand, test, develop. Code and templates should be decoupled, but in UI development, template is just the visual representation of behaviour (code), which means it makes sense to couple them. Plus when you develop in React, most of the logic should be outside of components in any case (I use Redux so it's in reducers and middleware + some util files).
It does indeed go against years of advice, but only if you look at it from too far out:
(Note: I've minimal Angular experience so I won't comment on that. I've spent the last year on React)
The real problem is mixing business logic and presentation, not mixing HTML and JS. React is purely presentation & presentational logic (or should be, you can of course implement it poorly)
For Presentation, the HTML and JS are always coupled, whether you have them in separate files or not. So in that sense, all React is doing is admitting a truth.
While embracing the coupling of that mix, React is ALSO pulling out a lot of logic: React encourages one source of truth (the state is in one spot, and drives the markup, but you never consult the markup to determine the state). An error that is commonly seen in, for example, jQuery apps, is that some state is hanging around in application variables, while other times it's in the current markup state, and the app will consult the markup to see what's happening. That's not a built in jQuery problem, it's just a common problem of implementation.
I'm not sold entirely on the React boat, but it does seem to directly address problems that I've encountered in other systems, and I expect whatever comes next will build from React principles rather than reject them.
> For Presentation, the HTML and JS are always coupled, whether you have them in separate files or not.
Absolutely not. Back when we were all just using jQuery, you could run $('.some-class').myWidget() to activate a widget on any element matching the query. There was no need to couple the implementation of the widget with the element to which it was applied.
If the widget had some internal element construction to do then yes, I would agree, it makes sense to have it be part of the same file, and this was often done with string concatenation back in jQuery days.
However, there is still value in being able to share the same html template across multiple models. You may have a general tabular structure you want to adhere to app-wide but you may want to implement different dynamic logic to those tables in different places. Now you're faced with having to copy/paste the same template over and over in React to accomplish the same task, or you have multiple mixins that define different behavior which kind of defeats the purpose of having the logic and the markup live together.
> If the widget had some internal element construction to do then yes, I would agree
...which covers most everything, really. Also, in the React world, if you just need to manipulate the data passed into a component, that's all pure JS. Only the component itself (with a reference to the passed-in data) would be JSX, which is distinctly more friendly to work with than string concatenation. (and I say that as someone that hates having a build step)
> However, there is still value in being able to share the same html template across multiple models.
...
> Now you're faced with having to copy/paste the same template over and over in React
I don't think you understand the concept of a React component, or I've misunderstood what you are saying. Make that template once and just use it wherever needed!
I have some complaints with React, but lack of reuse and JSX being worse than the alternatives are NOT among them.
Yes we do. I've been in a very similar position as you are - I was complaining against putting HTML in JS, however I've changed my opinion after actually started using React professionally.
From the side it might look like a bad practice, but I promise - this "HTML" in JS leads to fantastic testability. And I certainly prefer to work this way instead of filling HTML with numerous of "ng-" attributes where you're trying to force app generate code that you want.
Sidenote: even though it looks like HTML, it is not exactly HTML.
Putting HTML and JS in different files doesn't make them separated. They are still bound by logic. It's an imaginary separation with obscure dependencies. I very much prefer the React way of bundling things that in reality belong together.
Except this isn't about style. It's about logic. Logic isn't as optional as style, and if you separate the logic into one JS file and the DOM into another HTML file, they are still tied together by the JS binding some action to some named DOM element (by selector, etc).
The separation that scales is the one that pairs a small piece of DOM (like a piece of text on the page that updates with the current stock price) to the JS that goes with it, and put that into a single file. Now, build your web page out of components instead.
So this is where you enter a slippery slope from web page to application.
Developing a webpage and adding progressive enhancements to HTML elements is a strongly advised best practice with numerous advantages.
Developing an dynamic application at the complexity of say Photoshop it would be absurd to have a static HTML file with behavior decorated by JavaScript, or try and offer a fallback. Whilst you could in theory perform you photo editing with form submissions and round trips to the server I am not sure it would be worthwhile (I did actually create one circa 2004).
I'm a fan of practicing "stateless development", where years of "thats what we've always done" has no bearing on what I'm doing now. Writing HTML in JS is much more pleasing than cramming JS into HTML via Angular.
After working quite a bit with AngularJS, trying to read HTML with a ton of AngularJs is nearly impossible at times.
React is way easier to read and makes a lot more sense to my modular thinking about code. It also works naturally better for SEO compared to AngularJS.
It turns out there is no good reason to separate code and templates, because they are intrisically linked; one cannot work without the other. The separation should rather happen on units that are really independent, such as 2 separate pages of your application.
Yep, it was an old rule for an old time when back-end functionality, UI functionality and presentation could all get jammed into one *SP or PHP page. While the times changed the common wisdom remained. There is no reason for a component that's sole purpose is to be a component should not be self contained. It is a black box to the consumers.
When I first began delving into reactive client interface frameworks. This was one of my biggest gripes. It looks, and reads like a giant confusing mess. I finally came across http://vuejs.org/ and I haven't looked back. Simple binding syntax to html elements, and powerful enough for most projects without being heavyweight.
I mean it doesn't get any more straightforward than this.
Here we use https://www.jsviews.com/ in a similar way by having the templates in .jshtml files and calling them from the .js ... I wouldn't want to put the html directly in my .js files either!
It does result in a tight coupling of template and code, but I'm yet to see a downside to that. Separating template and logic has been the dream forever but is never realised in any non-simple project. Embracing that coupling has been great for me.
In Angular separating logic and html works fine. The only type of component that should be dealing with html in the first place, are directives. Directives point to a piece of html to include, which can be either a string or a url. In the case of the url, the code is separate.
But more important is the separation between the directive and the rest of the code. The directive is specifically about the logic that's directly related to the view. That's not something you want to put too far away from the view.
And of course Angular's html is enriched html: by including directive, you can put databinding, and limited logic (generally about when you show that bit of html) directly into the html. Separating those would be frustrating and a bad idea. If your view is dynamic, that logic should be considered part of the view.
And of course Angular's html is enriched html: by including directive, you can put databinding, and limited logic
Either it's logicless or it isn't, surely. To me, databinding is absolutely the kind of logic that shouldn't belong in a template in the world of strict code/template separation. Another reason why it doesn't really work.
Not all logic is the same. There's logic of the type: "this is what we want to show, and we only want to show it if X is true", and there's logic of the type: "here's how we calculate it and that's all the complex stuff that X depends on".
If you refuse to put the former in your view, you're making your code a lot more complex for little gain. But if you put the latter in your view, you're making your view unreasonably complex and hard to read.
Neither extreme is good. You need separation of concerns, but some logic really does concern the view directly.
I see "components" as a slightly different way of thinking, where you're building a cohesive unit. There'll be coupling between template and code, because they are by definition a single "thing." And they should be small in scope -- render a single bit of data, or have some other well-defined, small duty to perform.
Even in Angular, where we try to separate the template from its directive/controller, I don't think I've yet run into a case where I can just reuse a template with a different directive. And in fact, if I was about to do that, I should rethink my strategy (and probably just use the existing directive).
You don't have to, you can work with React straight from vanilla JavaScript though. I don't know anyone who does it though (except in tests), because it's nearly not as pleasant to work with as JSX.
It is possible to separate JSX elements from the rest of your code if you use ES6 React components or functional components (that is, you don't use React.createClass), because in those cases there is no need to compile the components themselves, so in theory you could separate the "HTML" bits into separate, dedicated files. It's not really a problem I've faced so far, but might end up doing in the future.
A lot of recent trends feel like going backwards to grumpy-me as well. Microservices being preached basically the same way SOA was (and falling on every single pitfall again), languages where copypasta and mutable state are "the idiomatic way", HTML inside js code.
Granted, not all recent developments are bad, of course - eg compiled & typed languages being back in "fashion" is a good development imho. It just feels to me we're either not very good at passing knowledge down or just collectively don't care much about learning history to avoid the same mistakes.
It's a squick factor issue. When you're trying to break down templates as small as possible, everything tends to become a bit icky in templating systems anyway. Consider -
[% BLOCK foo %]
<td>[% payload %]</td>
[% END %]
...
[% INCLUDE foo payload=something %]
in TT (perl's Template Toolkit, which I'm about 98% sure pkrumins is familiar with already), and then
Once you've got a bunch of them in the same file, I don't honestly find the JSX much different. The trick for me is to have the HTML in .js files that contain only pure functional rendering components - so when I'm editing those, I can think in HTML and just treat the JS as a slightly weird template syntax - at which point the squick factor mostly recedes.
Yep, things change. Personally it always felt weird to have html separated but I was doing it because I had "html/css integrator" on the team, and it was easier for them to deal with html-only pages. But now, most front-end developers do it all.. html/css/javascript so it makes sense to create the best experience for them. And it just so happen that html is completely tied to components so there's no point in separating it.
Basically, adding html to javascript is much more powerful than adding "some" parts of javascript to html. Every time I go back to django and need to create filters and other craps to put something in the html I feel like I'm wasting time with bureaucracy.
For what it's worth, I think the maxim "different kinds of code should be on different places" is deeply wrong and perhaps the biggest current impediment to code quality in the web world.
The alternative view is "things that are tightly coupled should live together" which I think is generally a better maxim.
In theory views can be loosely coupled, but in practice they seem to be almost always coupled 1:1 with whatever layer is above them, controllers or view models or whatever.
I can't say for Angular but the thing about React is that it is the V in MVC. The fact that JSX apparently mixes JS (logic) and HTML/CSS (presentation) is kind of a red herring. The JS logic in JSX is actually the view logic, not but ___domain logic!
Also, as an experiment you can prove to yourself that you can separate out all the actions, views, and states in React. Here states=model, views=view actions=controller -- but wait you say, this is MVC so React is in fact MVC and not V! No! The thing is MVC can be arranged hierarchically into levels, so you can have M(MVC)C... if you like :) Don't believe me? Check it out: https://en.wikipedia.org/wiki/Hierarchical_model-view-contro...
I felt the same as OP when I first started using React, although it makes more sense now I've played with it, I'm still not sure about mixing concerns (code and view) in the same file. Especially when you start talking about CSS too...
I hadn't heard about JSX before so I went to your link to check it out. This is just one of the most off-putting introductory statements I've ever read:
JSX is a JavaScript syntax extension that looks similar to XML.
Don't we all hate XML? How can you possibly even go on reading about this technology further if it's introduced like that.
XML is still used as a the standard for building layouts - on the web and on Android, and probably many other places. It can be much more readable than code for nesting components.
I believe people hating XML has more to do with using XML as a data transfer format, right? I'm happy using XML for Android layouts but can't imagine using it as a replacement for JSON - which I think is where most of the hate comes from.
XML is fine. XHTML is XML, after all. The issues with XML are the kind of XML that is often created with it, with namespace nightmares, endless embedded tags, etc. etc.
But if you're using XML to basically make a variant of HTML, it's great.
No it's not getting preprocessed to actual HTML in React. Depending on the transform function, it can be turned to an object tree or a function calls tree (like in React) or actually HTML like you said but it's not a common use case AFAIK.
It's not a text templating language like classic PHP, it's an object/function calls hierarchy DSL (more like vb.net XML literals). I think most people critisizing react for putting html in JS havn't tried it or don't remember why "html" in code was considered bad in the first place.
Concepts should be separated. Layers should be separated. That's true for any application.
Separate HTML and JS? That's a small implementation detail. You can have your view layer as JSX files, separated from business logic, data access, etc. That's actually recommended.
Even when you are using purest HTML template engine, completely separated from JS logic, you still can make a mess, moving lots of logic into HTML or moving all your layers into a single JS file. File boundary is very artificial separation. It doesn't always help. And often it makes things worse, because you have to work around limitations.
One of the features I always liked about Perl, which I felt set it apart from other languages, is the way regular expressions are part of the language syntax rather than an OOP library. In other languages, regular expressions seem very clumsy to use, while in Perl they're very natural. This is most evident when you're trying to use capturing parentheses; the differences between Perl and, say, C#, are huge.
Back in the day, I thought it would be a great addition to Perl if xml/html was also added to the language syntax. This was before html templating systems existed, and CGI.pm wasn't a good choice for my web application, so my code was full of print statements, quoted strings containing html, and having to use qq!...! for my quotes to avoid problems with " and ' characters in the output I wanted.
When I first saw JSX it seemed like a great thing, finally satisfying that old desire to have html markup as a native language syntax feature. I feel like it can be transformative, in the way you write your code, just like Perl's regex syntax or like having functions as first-class values can be in functional languages.
Having used React.js a bit, I'm not so sure. But I'm probably biased because I don't think React.js fits well with what I'm trying to do: ASP.NET MVC web applications that are mostly traditional full-page-refresh style apps, with some SPA-like AJAX-based interaction on some pages. I wanted to use React.js for those SPA-like pages, but it doesn't integrate well (or at all) with Razor-based server-side rendering, and in my testing it had a significant 1000ms+ startup time when the page loaded even for pretty trivial components, with caching of the React and Babel javascript files.
One way to think about it is JSX is just another templating language that happens to be a superset of JavaScript. You are free to use as much or as little logic as you like, but the trend is definitely moving towards keeping most components simple and free of complex logic.
With "stateless functional components" (added in React 0.14) and ES6 you can have "templates" that look like this:
1. It's not HTML, it's JSX, a vaguely XML-ish DSL that is compiled to JS. You can (and some people do) write the underlying JS code directly. But, obviously, writing a DSL that compiles to 'React.CreateElement.Div()' is the same (at least as far as seperation of concerns) as writing 'React.CreateEleemnt.Div()' directly.
2) Best practices focused on separation of concerns, and in particular, on avoiding embedding logic into your static HTML. The canonical example to avoid historically was to put JS directly into a links href attribute, but some have suggested Angular is guilty of something equivalent with its ng-* attributes.
3) Conversely, React advocates agree 100% on separation of concerns, but feel the "nothing that looks like HTML can be in the same file as something that looks like JS" injunction is actually an example of separation of technologies.
It doesn't have to be a debate, everyone can move any one language into the other (JS into HTML, HTML into JS, CSS into JS, etc), as long as they feel that what they write will be something they can reason about later. They should take into account their mindset in 6 months, other people that might be brought on and what their background might be.
The only real issue I see is that if you move HTML into JS, you might make it harder for a pure visual designer to step in and work on HTML/CSS, but outside of that I can't see an issue as long as you keep reasonability of the code in mind. And if you have a good designer, I have a feeling they'll be more than glad to learn how to navigate around Javascript.
It's all "View Code" so separating HTML/JSX from "view" JS (as opposed to separating HTML/JSX from "logic JS" in handlers/reducers/etc which is a legitimate abstraction) is very superficial abstraction and gets in the way of comprehension. But if your brain refuses to parse HTML in JS then you can always specify the DOM fragments as JSON in your render() function.
The thing that I don't agree with about the blog post is the inclusion of State in the main App props in the form of maxSomething (forgot already the prop name) App configuration should be gathered in one place as a set of constants, IMO. App state should only contain the data, not the meta.
I found it to be a huge productivity boost. In highly interactive apps, templates and code are connected so much, trying to pretend that they are not and switching back and forth all the time for me personally feels like fooling myself.
It depends on your perspective. If you're building an application that passes disjointed components around, then yes, you can combine the three (js,html,css) into a self reliant container. If you're building a website that is basically a series of pages, that is part of a book per say, then it doesn't quite make sense. I would say 10 years ago it was not common to think of the web as a platform. Over the last 5 years using the dom as platform and js as the source code has become much more predominant.
Whether the scope of your business can be used by this architecture would determine whether it would come up in your day to day.
The early web days were spend developing basic web pages without any complex tools.
These days everyone seems to think they need an application style site, and whilst some sites really do benefit from this approach, others don't.
The trinity of web standards (html/js/css) are still valid for informational, mostly static web pages, but are impractical for developing applications.
The discussion of what is a web application is a tricky one to put a finger on, with a lot of grey area. I think of a classic web page being the about us page of a website, while an application is something like photoshop. In between you have things like twitter, or gmail, amazon, facebook etc.
I think what qualifies a web application is the introduction of state and enabling the manipulation of data. Static sites, or dynamic websites without the state problem to the end user, are naturally better off without a client-side app approach (though ajax is still beneficial and structuring your approach to ajax can make client app frameworks/libraries tempting)
However, when you start giving the user powers to manipulate data and make the manipulation of data a core function of a website, it becomes a web application.
Photoshop is an extreme example of a web app really, and perhaps the most basic web app would be something like a CMS or a forum. Hence why social networks and email clients are created as apps now: they involve repeated display and manipulation of elements which are liable to change.
Initial attempts to improve the user experience of such tools as online chat and mail were made by using Ajax and this has culminated in asynchronous Ajax and virtual DOM models in order to achieve a real-time effect without sacrificing accessibility and performance.
We went from reloading entire pages to reloading bits of pages to never loading those bits but rather constructing them on the front-end drawing data from APIs.
Now with React and similar libs, we are looking at a hybrid approach: exposing data via API but (ideally) constructing and emitting HTML on the server before pushing the app to the client where a virtual abstraction of the DOM is established, but where data can still only be manipulated in one direction. This means that there is no state issue, because while routing and other interactions are achieved client-side, their composition is determined on the server.
It's almost a dialectic cycle of thesis, antithesis and synthesis.
> Hence why social networks and email clients are created as apps now
I think a large part of the definition of "application" is subjective, personally I think social networks, such as a forum or twitter suffer from being an "application". You want to benefit from SEO, fast loading, responsive design, accessibility etc. However a chat app, that's personal and contains ephemeral content is a much better candidate for an application. I expect to see a different setup from other users, I don't want it to be searched, I expect different experiences on different devices etc.
Another good example is tweetdeck vs twitter. One is very personal and customizable, the other is essentially a generic and universal between users.
I think we are entering a phase of "everything is a single page app" because it's interesting and exciting. Similarly to the early days of mobile of flash development. Hopefully in a few years there will be a renaissance of the simple webpage, and application frameworks will be reserved for the use cases they really make sense for.
This is a common misconception. You're not actually writing HTML. You're writing `React.createElement` calls in an HTML-like syntax. This is just to make it very easy and fairly pleasurable to write your templates out.
Nothing prevents you from not putting HTML inside JavaScript when using React. Personally I've found that this JSX approach doesn't integrate with certain editors very well, so I just use raw React.createElement calls. Assign it to a short variable and it really isn't bad at all. I even tried a s-exp syntactical transformer, and it works even better. HTML is basically just s-exp with an ugly syntax, so it feels even more natural doing that.
Only in the appropriately named render method, which will use code to choose what to render and not to do anything else. How else would you satisfy the requirement to display a list of items and a special item if the list is empty?
The danger you run into is PHP nightmares where the programmer has e.g code that accesses and fetches items from a database in the middle of the view.
This is not traditional HTML from the early days and because it is not it has a higher chance of reuse outside of just an internet webpage, and makes it easier to transfer across other view layers, canvas, native desktop/mobile views, etc
In the beginning of JS+DOM, it was a common practice to write HTML with DOM events (in JS): (`<button onclick="doSomething()">`). Server rendered most things anyway so you could (`<button onclick="toggle(<%= someId %>)">...<div id="item-<%= someId %>">...`).
Problem was tons of global functions all over the place, or many big objects and maintainability issues.
In the "jQuery era", you'd write your initial HTML in .html files and jQuery all the events. It brought infinite amount of ways to write code, which often led to many styles and no conventions.
<button class="show" data-text="hello">+</button>
$('.show').click(function () {
var $this = $(this)
var $div = $('<div>').text($this.data('text'))
$this.after($div)
})
etc.
Many problems with this approach:
- You can't tell which element has events bound to it just by looking at it. Any JS file can decide to do that
- Usage of a CSS class to find elements is just a hack
- Poorly named IDs/classes create collisions
- After an action, the initial HTML no longer represents the current state
- Server can render some HTML, then client changes it, and if things get out of sync, the only way to reset the state is to reload the entire page. Imagine a user signing in, and many parts of the page need to show things for a signed in user. Doing this manually would probably be error-prone, so it's just easier to reload the page and let the server do that.
And then came the modern front end libraries/frameworks like React, Angular, Ember etc.
The main difference is that now the HTML representation is ALWAYS in sync with the data, AND the functional code that's attached to each element is at the same place.
Yes, it's one of things in ReactJS I don't like (inheritance is the second), but people like it. People tend to like what is easier to do, until they know bad consequences.
Can you link to some? I haven't seen any, if I had, I wouldn't be asking this question. It's been bothering me for a while. I've tried searching for "putting html in react", "html in react best practice" and similar queries but they don't find those thousands of threads.
Well, that is not really something every React.js beginner should know. Feels weird to say that a X beginner should learn framework Y since he is probably just interested in X...
> 6. Always use propTypes
Worth mentioning that this slows down your application since React needs to check all the props. Don't forget to set NODE_ENV=production when compiling your production script.
You're absolutely right - the power and benefits of libraries like Redux are so obvious once you've grokked React but as a beginner it really is just going to slow you down or just get in the way of learning.
This is partly because of the overhead of having to learn another library, and partly because you have to learn by making mistakes, experiencing the pain, and then badly hand-implementing parts of Redux yourself to truly understand its value, and how it should be used. At that point you're way beyond beginner level.
Same goes for '8. Use JSX, ES6, Babel, Webpack, and NPM' - JSX aside, setting up this tool stack is totally unnecessary for a beginner getting started hacking on a Hello World app. This is something you do after you've learned React, and you want to use use it in a 'real' project. Depending on your knowledge of these tools it could take literally days of work to get started.
I'll be honest, if someone with no knowledge of React asked me how to get into it, I'd also be tempted to mention Redux or Relay, the tool stack, all those things in the React ecosystem that are fantastic and essential for a real production React stack. But it's just too much information, it's not what a beginner wants or needs to know.
I think there's a general lesson here - learning frameworks, how they fit together, and what tooling to use is really complicated and only seems 'obvious' once you have the big picture. You have to remember what it felt like when you were a beginner, and just wanted to learn the basic rudiments of React itself - that's more than complicated enough to get started with. When giving advice to beginners, it needs to be laser-focused, ignoring everything but the exact thing they're interested in learning. Forget about all the extra stuff they'll need in the 'real world' - they'll figure that out along the way anyway.
Same goes for '8. Use JSX, ES6, Babel, Webpack, and NPM' - JSX aside, setting up this tool stack is totally unnecessary for a beginner getting started hacking on a Hello World app.
While I agree with you in theory, in practice learning how to use Babel/JSX and probably es6 are pretty essential to react. All the tutorials are written using JSX which necessitates a transpiler. And a ton of the supporting libraries are now in es6. If you are going to use react you're really going to need to figure out the es6 tool chain.
Agreed - I did say JSX aside :-) JSX is coupled so tightly with React, and such a large part of React's offering, that learning React without JSX is probably actually going to slow down learning for the opposite reasons.
In general, ES6 is a prerequisite for developing anything in JS for any developer/project with a forward-looking mentality in 2016 - but I do have to disagree that knowing ES6 is essential for learning React. They're actually completely orthogonal at this point - it allows for cleaner code but doesn't buy you anything at all in terms of learning the React concepts.
As for getting started on the Babel toolchain - again it's orthogonal to learning React. The in-browser JSX transpiler is available. You can start learning react in a single page of html with script tags, just pulling all the libraries off cdns. There's just no need to have a tool chain at all, it is not essential.
I think it comes down to the definition of beginner. If you're taking a very experienced JS developer and starting them on a real world React project, by all means go in at the deep end - they'll likely know most of the toolchain anyway and they'll need it. If you're talking about just giving someone an intro to React and its concepts, you have to separate the core from the ecosystem.
My point was that we should recognise the difference, this is a common problem where experienced users tell beginners to 'just use' things that take months to become accustomed to in a few throwaway sentences, because to them it is just that easy. To a real beginner it represents a massive ramp, and that's not what you want when just trying to get an intro to a specific library.
Well, if you set out to learn React (which this article is about), you are only learning React. Not even V in MVC because probably you're not out after learning MVC. You're out after learning React.
You're not learning MVC, you're learning React. For example: I'm not learning software development, I'm only learning javascript. I don't want to also learn sql so I can make the backend storage.
I was addressing the second part of your comment. TypeScript is a static type checker. It operates at compile time. There is nothing to "disable" at runtime.
But yes, regarding your original question, you are correct, aggressive optimization is a non-goal of TypeScript. It won't improve performance.
Neither this comment nor the article clearly spell this out: when you use the production version of React, much of the developer-assisting error checking is removed (not just propTypes[1], but many other error checks[2]), so you don't need to worry about the end-user performance impact of propTypes.
As an example of how much this helps, one React-heavy page of mine dropped from 1500ms to 300ms by switching versions, according to my browser profiler.
OP is talking about compiling react in prod mode yourself, having pulled the source as an npm dependency, as opposed to pulling in the pre-built prod version with a script tag.
See the npm section right below the Individual Downloads section you've linked to in [2] - this is the recommended, and more common, way to use react.
Good that with Google you can limit your search to a certain time frame. Personally, when I Google stuff about React, I set filter to "Past month" so that most results are quite up to date.
I wonder if in the future the project that you start doing in the morning will use outdated libs by the evening ;)
Does this not seem like a problem to anybody else? Wasn't the whole point of React that it was supposed to be simple? And yet things have gotten so complex you're giving advice that anything older than 3 months isn't even worth reading?
I really don't understand the underlying complaint of your comment that the React ecosystem is in constant flux (see what I did there?)
I've been writing React SPAs for roughly two years now.
Very few things have changed. The first app I've written roughly looks like the newest one. Couple of lessons learned here and there like everywhere else.
Yes, there are many Flux libraries and different implementations. However, a decent State management solution for React is roughly 200-300 LOC. So there are many of those 200-300 LOC libraries. So what?
If it's a big project, you should spend the time to figure out what fits YOUR project and YOUR team the best.
If it's a side project, use the most popular with the best documentation and be done with it.
The biggest advantage of this progress is that there is a lot experimentation with new kind of tools (for example Redux Dev Tools. This is fascinating. I mean Redux is great, but the fact that there are dedicated dev tools for this? Wow. I'm waiting for new tools (maybe every popular library from now on will have its own dev tools? Or maybe somebody will make universal dev tools for all React libraries?).
I think what's happening inside React ecosystem and this constant flux of innovations is not comparable with anything in the webdev before (maybe except Ruby community which is also pretty innovative).
You can run "webpack-dev-server", which uses your Webpack configuration to serve your scripts with its own web server.
That means (1) it can do incremental recompilation, which I can't live without since my build takes 20 seconds; and (2) it can block requests while compiling, which is way better than having a background thing (e.g. watchify) recompile your code, since it means you're never interacting with a stale (or god forbid partial) compile.
The dev server also does automatic page reloading on recompile via some injected script magic. In my case that means I often don't even need to alt-tab to see my updates, like if I'm messing around with styling.
Webpack also has a whole paradigm that expands the use cases of require() in a pretty interesting and useful way. For example, you can tell it that require("../../icons/lolcat.png") should resolve to "static/lolcat.[8 chars of base64 SHA-256].png" and also do the appropriate file copying. Or you might want require("./stuff.csv") to resolve to a parsed JSON table, or any such transformation. There are a bunch of plugins for common uses. It's common to use require() even to load your CSS, because then Webpack can handle running it through your auto-prefixer or whatever.
It might seem kind of bloated, and I love Browserify for its simplicity, but I've come around to really like Webpack now that I've spent the proverbial 4 hours.
FYI, browserify has support for all the cool tricks you list too now; it's just a question of finding and wiring up all the right plugins.
Eg, lessify, css-modulesify, or csvify will handle the cool require tricks, browserify-hmr does the fancy hot module replacement, watchify has incremental recompiliation support if you manage to configure it just right, etc.
Mind you, I find webpack easier to configure (all the fancy browserify plugins destroy it's simplicity), but the two toolchains have had feature parity for a while.
I think Webpack has the monolith advantage here. It allows you to add things that would otherwise be immensely complex with ease because it can do a lot. You can have it handle bundle splitting and async loading of modules, image optimising and hashing, CSS/SASS/... processing, ...
Since we started using Webpack where I work we've stopped using all other build tools. There's very little Webpack can't do, and the main advantage is that there's no need to hook things up to eachother since it's all part of the same system.
Yes. Also, it will build faster and the configuration will probably be simpler. That's been my experience having used Browserify with Gulp and Grunt for 2 years and then switching.
Webpack does everything Browserify does, but arguably if you're used to both the configuration is marginally more transparent (although still terrible). Also, arguably, new features tend to land in webpack a LITTLE earlier than browserify, which might be important to you in rare cases.
In short, I've used both, and I'm currently happy with webpack, and I have a decent configuration on my current project with a dev server, good production builds, support for CSS modules, and hot module replacement, all of which I could have in browserify.
Oh, webpack makes it a lot easier to dispense with gulp; my last browserify config was driven by gulp, but my current webpack config is just driven by a few lines of vanilla node.js code, which is kind of nice.
> What part of my life would actually get better if I took the 4 hours of my life I will never get back to make this switch?
Probably none of them. But if I had two boilerplate configs, one using gulp+browserify and the other webpack, I'd choose webpack because I think it's VERY SLIGHTLY clearer and more maintainable.
I'd probably look into switching to Webpack on future projects, but I'd rather french-kiss an angry squirrel than spend a half a day wrestling with my app bundling code again, so I'll stick with Browserify for this one. :)
Here's their comparison with browserify and others: https://webpack.github.io/docs/comparison.html.
Personally, I use browserify because it is ultra simple to get set up. No config file, gulpfile or anything and I'm using es6 and watchify to auto recompile. We use webpack at work, it's more performant and has some nice features, like using it manage your css and images as well, but getting it set up can be a headache.
If it works for you stick with it. I started with webpack for the same reason-- I wanted to use ES6 syntax, and a coworker had some boilerplate that did most of the work for me.
I'd say "Write functional components where it makes sense". For simple components that is a reasonable advise, however in cases when you need such methods as `componentDidUpdate` or generally any lifecycle methods - that won't do and you have to use classes.
Not a React guy, but why couldn't the component that updated broadcast that it did so? Or is that componentDidUpdate method a callback to the message I'm describing?
Depends on what kind of component just updated. If it's a low level text field, it probably shouldn't broadcast the change to anywhere else in the program. Instead it would invoke it's 'onChange' callback. This way, there are no extra dependencies for making the text field component work. The parent component always provides the onChange callback and takes action accordingly.
However, if the component that just updated is high level, like an entire page or something, then it's reasonable to assume it's a one-off controller component and you should feel free to broadcast messages and couple the component with other parts of the program.
In addition to what lopatin replied to you - sometimes your component have to subscribe to some window event - for example 'resize'. I'd say it is way better to handle this event attachment/removal within the component instead of inventing some convoluted system of events in the root container which broadcast changes.
There's a number of situations when functional component just not enough.
Fantastic article, in the past 9 months you've hit on nearly all of my discoveries.
Something I do now every time I create a new react app is to create a base class that extends React.Component that uses `PureRenderMixin`. When doing this I can prevent unnecessary renders from props changes. A killer of this would be passing an prop to a child that always changes its identity, like passing a function that calls `bind`, Because bind create a new method every time its call the identity always changes and the method will always be re-rendered. Knowing gotchas like these can help really speed up apps!
What really bothers me about React (and other frameworks) that without JS you do not see anything. No fallback. No progressive enhancement. Is this really the way to go?
Did JS replace HTML/CSS as the backbone of websites/applications ?
This isn't strictly true. Though the workflow isn't ideal yet, it's perfectly possible to build a React project which is initially rendered on the server and then progressively enhanced. I've done it before, as have others.
In fact, my single biggest criteria for any tech I add to my stack is that it doesn't get in the way of server-side rendering (the second biggest criteria is that it doesn't add significant weight to the client-side JavaScript payload).
That's not generally true. React is specifically designed to support progressive enhancement. It lets you render your pages on the server, and then the client-side JavaScript will work smoothly with the existing DOM. Redux is a popular state management library for React and it is also specifically engineered to make server rendering painless. All you need to do on the server is load the relevant JSON state for the given URL and give it to React.
I'm with you on this one. Although I use React actively I still have problems with the fact that you won't see content of the app without JS on initial load. Sure, there's a matter of isomorphic applications where React renders content on server during first call, however after trying several times implementing it - just ended up abandoning that idea due to how massively complex various things become in certain cases with authorizations for users and so on.
In the cases where react makes sense - where the users change data together or where new data is often enough generated on the server, yes. Try to make Trello work as well as it does today without javascript - ain't happening, you would be reloading every few seconds in case somebody else has made some changes.
On e.g a newssite react doesn't make much sense though (except, possibly on the backend).
And without JS you don't get real applications on the web. Dumb text is fine for web 1.0, 2.0, but modern web applications are expanding far beyond that. Are there ways to be abusive with JS? Sure. But JS is what enables web applications as opposed to just having text-on-page (newspaper 2.0).
This is simply not true. Ignoring the fact that "real application on the web" has no definition... very useful web pages can be created without JavaScript, and they can (quite easily) interact with the user by taking input and updating what they display.
Why is something like that useful? Accessibility, security, backward compatibility, ...
Honestly, it's 2016. Running a modern web page and browser without javascript is just silly. You're losing out on a lot of quality of life features, that people just expect to be there. It's the equivalent of taking away a touch interface from modern mobile phones.
I think Dan is making a different point. He's saying functional components are just like regular components in terms of speed. The author of this article is saying use functional components so it's clearer when a component needs to be split up.
I have to admit I find the author's insistence on defining a component as a function to be a big red herring. Instead, it feels like the presence of JSX outside of the component's render() method is the (potential) code smell.
It doesn't help that several popular React & React Native tutorials out there, for understandable simplicity, opt to use "renderSubThing" methods. In the examples and in my own code so far, I mostly find those sub-render methods to be a proxy for "I don't want to break stride to make a new component, so I'll jam this stuff in a method and refactor later." That's great, so long as the refactor actually happens.
(Hm, that'd be a great candidate for a vim refactoring plugin...)
I've seen it mentioned by a few people, including Redux creator Dan Abramov (who is very open about tweeting links to 'competing' libraries!), but I've only taken a brief look so far.
My initial impression is that it seems really interesting, although I wonder if the use of generators will scare people away. Many devs are already exhausted with the number of new JavaScript features they're being told to learn.
I definitely want to dig a bit deeper and try it out properly though.
Best comparison I've seen so far is that it's sort of like "background processing threads for Redux". The downside is that it might not mix well with time-travel debugging, because a saga effectively has its own internal state.
That said, Dan Abramov does seem to think it's a very intriguing approach, so it's worth keeping an eye on.
Great article! As we have been on-boarding developers with React, we noticed that all of the boilerplate needed to get Babel, Webpack, Redux, and a testing environment (we use Mocha, Karma, and Chai) was simply too much for most people to handle while beginning something new. There are lots of boilerplate projects but telling someone new to fork a project on GitHub and start building an app from there was raising some eyebrows as well.
That's not all, there are really amazing developer tools available for React development like the redux dev tools, and hot module replacement to name a couple. These tools are extremely helpful to beginners but a beginner is not going to enjoy the extra work of setting that up as well.
Imagine if you were going to build an app with Rails and the instructions were to follow a tutorial that had you manually hook up active record, create your bootstrap files by hand, write your own code to rebuild the server ever time code changed… or even forking a boilerplate Rails project and going from there. I don't believe Rails would have become what it is today without the Rails CLI.
What happens when the boilerplate changes? What if you find a XSS vulnerability in the boilerplate project that you used in your last 10 projects. Rails developers have identified and quickly patched several security vulnerabilities over the years. It's usually as easy as updating a gem file to patch your app. With the boilerplate approach, you would have to manually update all of your apps or try to merge the update from the project your forked. That isn't going to be fun at all.
Finally, one of the coolest things you can do with React is server side rendering to build universal apps. At this point, even if you know exactly what you are doing, setting up a new app is going to give you way too much work just to get started. So you'll need to find a boilerplate with server side rendering and fork it. There are way more opportunities for security issues when you increased the surface area of your app's responsibilities. There will be updates to this boilerplate and you will have to merge them into all of your apps. I hope you like manually updating files and resolving merge conflicts on files you don't really understand…
We set out to resolve these problems when we built GlueStick (https://github.com/TrueCar/gluestick/). It's a CLI that allows you to quickly generate new apps using all of the tools we like to use on React applications. You have generators for creating containers (smart components hooked up to redux), components, and reducers. Redux is set up out of the box. You have server side rendering out of the box. We also push as much of the boiler plate code into the GlueStick module as we can. This lets you easily get performace and security updates as well as new features by simply updating the node module. You also get a sane folder structure so that all of your apps built with this tool will be easy to navigate.
We built this tool at TrueCar but we open sourced it. That means you can take it and make it your own, contribute back if you want to improve it and you can rest assured that it is backed by a big company that is heavily invested in seeing it succeed.
Nice, I like this a lot. I think it's the cleanest and most concise approach I've seen re: universal React/Redux.
Is there a way to override or extend the webpack config though? (without having to fork it) What if some projects need different loaders or want to use code splitting, etc?
We have plans to implement this. I don't think it will be too hard to implement. The hard part will be coming up with a clean approach for developers as they build apps. It is on the list of things we would like to add. A PR for this would be greatly appreciated :)
How about TypeScript/TSX?
React's components and "views" are easy to type (and you get completion in your IDE) but I still have to find a convenient way to type an Immutable map where each key/value pair has a different type (the equivalent of a TypeScript object). Any idea?
you can use the functional way of setState by passing a transaction function (state: State) => State . This allows for typed, immutable updates since the function gets passed a copy of the state.
The truth is, libraries and frameworks both end up being equally complex to work with, precisely because the problem of building large applications is inherently difficult.
It all comes down to personal preference:
Are you the type of person who is more likely to believe you can do something better than everyone else, or are you the type who is more likely to defer to those you believe to be better than you?
Are you decisive or do you agonize over the smallest choices?
Do you feel a compelling need to understand how everything works, or are you willing to implicitly trust other people's systems?
I find it amusing that people who gravitate toward smaller libraries like Backbone.js and React.js rail against frameworks like Ember or Angular for being overly complex, heavy, and "magical", and then proceed to cobble together a Rube-Goldberg-esque system of disparate dependencies to achieve the same goals. When React first started getting popular all you read about was how simple the API was and how it was Easy to Reason About™. Fast forward to today and you need to have working knowledge of WebPack, ES6, Redux, immutable.js, Babel, and a bevy of other dependencies to be aligned with the React ecosystem's ever-evolving best practices.
The exact same thing happened with Backbone.js and it will probably happen again with the next shiny new view-model library to ride the hype train.
It's important that I point out, however, that none of this is necessarily a bad thing. Smaller libraries like React.js and Backbone.js encourage a cavalcade of innovation from which awesome things like Redux are born. But let's not pretend that this doesn't result in a heckuva lot of churn for the average developer whose job is to simply get shit done.