Things every React.js beginner should know
camjackson.net
camjackson.net
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.
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.
"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.
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.
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.
Quite easy for whom, exactly?
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.
We build the framework that's suitable for our company. Once we got a thing going we use it for multiple projects.
If widespread use in production by Facebook isn't real world enough for you, then perhaps it's best to find a slower-moving part of the stack.
This is why Google's brand doesn't mean much in Angular's case (since most of their own products do not use Angular).
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.
When something functions on massive scale, it's commendable, and worth looking at.
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".
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.
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'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.
https://facebook.github.io/react/docs/jsx-in-depth.html
[NB Not that I know, just checking my own understanding].
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.
I'm also thinking in more of an Angular2 context as that's what I'm most familiar with.
https://babeljs.io/repl/#?experimental=true&evaluate=true&lo...
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...
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.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.
But if you're using XML to basically make a variant of HTML, it's great.
JSX is a JavaScript syntax extension that looks similar to HTML.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.
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.
https://www.youtube.com/watch?v=x7cQ3mrcKaY
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.
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.
JSX is just sugar for vanilla JavaScript. It's not HTML per se, as it's not parsed as such, but only as a means to create the virtual DOM.
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).
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.
everyone else please stop replying
Everyone please keep replying.
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.
Graphic designers were expected to know HTML/CSS while developers focus on PHP.
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.
Apart from here it is again...
So...like PHP, then?
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.
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.
I think what the commenter is saying is no one builds like this anymore in PHP, regardless of whether or not you're using a framework.
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.
It is only through laziness and lack of understanding that people couple them together.
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.
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).
The structure of your code does not have to dictate the result that is served to the user.
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.
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.
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.
WinAPI abides...
MVVM is nice regarding testability, but I find it to be overkill for most applications.
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...
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.
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.
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.
I mean it doesn't get any more straightforward than this.
<div id="app"> <p>{{ message }}</p> <input v-model="message"> </div>
new Vue({ el: '#app', data: { message: 'Hello Vue.js!' } })
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.
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.
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.
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).
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.
<MyComponent mySuperCoolProp={this.state.someState}></MyComponent>
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
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.
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.
Here's a function that always returns true - but it could do any kind of data access. It is just plain Clojure.
(defn selected? [] true)
Here is a datastructure that represents html: [:h2 {:class (when (selected?) "selected")} "Hello"]
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.spaceIt helps that Clojure's syntax is based on s-expressions, and s-expressions are already isomorphic to HTML/XML.
So in a way, you're still mixing your templates and your code, but you happen to be using the same syntax for both. Which is arguably an improvement.
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.
(defui my-component [x]
"<h2 class=(when (selected? x) ["selected"])>Hello</h2>")
[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... (defui my-component [x]
<h2 class=(when (selected? x) ["selected"])>Hello</h2>)
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 (defn my-component [x]
[:h2 {:class (when (selected? x) ["selected"])} "Hello"])The equivalent would be something like
function() selected { return true }
["h2", {class: function() {if (selected()) {return "selected"}}}, "Hello"]
Not as clean, but still usable IMOThe 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.
Not a good thing, IMO, since it makes the syntax way more complicated, but there you have it.
<div data-scope="users"><div data-attr="name"></div></div>
Now I have everything I need to process this html with my logic to turn it into
<div id="users"> <div id="user_1"> Frank </div> <div id="user_2"> Bob </div> </div>
edit: I wish downvotes required commenting on why you're downvoting.
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).
Either way, I _think_ I have a better understand of potential conflicting views. Thanks for taking the time to explain.
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.
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.
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
> 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.
[1] https://www.youtube.com/watch?time_continue=275&v=x7cQ3mrcKa...
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).
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.
> Separating state isn't the same as no state.
Any web page that has inputs or controls is necessarily stateful - otherwise where does the input go?
> Also imperatively updating the UI on state changes is stateful.
There's nothing imperative about it. Have you looked seriously at Wicket or are you just throwing buzzwords around?
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.
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.
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.
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.
[% 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 function foo ({ payload }) {
<td>{ payload }</td>
}
...
<Foo payload={something}/>
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.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.
React enforces 1-way data binding and renders everything in one clean pass (HTML/CSS/JS).
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.
Whether the scope of your business can be used by this architecture would determine whether it would come up in your day to day.
(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.
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.
...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.
So we have obfuscated the functionality embedded in our HTML with jQuery calls in separated files. Is this what you mean by decoupled?
> Now you're faced with having to copy/paste the same template over and over in React to accomplish the same task,
This is nonsense. Have you ever... used React? I recommend not opining on something which you lack even the most basic knowledge about.
With "stateless functional components" (added in React 0.14) and ES6 you can have "templates" that look like this:
export default ({ title, author, body }) =>
<div>
<h1>{title}</h1>
<h2>By {author}</h2>
<p>{body}</p>
</div>
I wonder if anyone has written a linter to enforce a "logic-less" dialect of JSX? Perhaps allowing specific looping and conditional idioms like: { array.map(object =>
<div>{object.whatever}</div>
) }
and { foo ?
<div>yes</div>
:
<div>no</div>
}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.
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.
$('<div>').append($(<h1>).text('...')).addClass('...').appendTo($('#selector'));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="toggle" data-target="item-<%= someId %>">
<div id="item-<%= someId %>">div</div>
$('.toggle').click(function () { $($(this).data('target')).toggle() })
or <button class="toggle">+</button><div>div</div>
$('.toggle').click(function () { $(this).next().toggle() })
or worse, <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.
And the jQuery example becomes this:
// react
<button onClick={::this.toggle}>+</button>
{this.state.isVisible ? <div>div</div> : null}
toggle() { this.setState({ isVisible: !this.state.isVisible }) }
// angular 1.x
<button ng-click="toggle()">+</button>
<div ng-if="isVisible">div</div>
scope.toggle = () => scope.isVisible = !scope.isVisible
When you look at this piece of code you immediately understand the ways it can be rendered and what affects it. Super clear, no surprises.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.
I do wonder if things like Typescript can solve a lot of the speed issues.
Typescript's type checking adds overhead just the same. So it's also a good idea to disable checks during runtime.
Fact: type checking is disabled during runtime.
Why would one assume that Typescript somehow solves speed issues? It has no measurable impact on runtime performance.
But yes, regarding your original question, you are correct, aggressive optimization is a non-goal of TypeScript. It won't improve performance.
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.
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.
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.
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.
[1] https://facebook.github.io/react/docs/reusable-components.ht...
[2] https://facebook.github.io/react/downloads.html#development-...
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.
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.
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).
Damn progress :(
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?
Thanks!
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.
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.
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.
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 feel like I get it now.
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. :)
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.
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.
https://medium.com/@dan_abramov/smart-and-dumb-components-7c...
There's a number of situations when functional component just not enough.
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!
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).
On e.g a newssite react doesn't make much sense though (except, possibly on the backend).
Why is something like that useful? Accessibility, security, backward compatibility, ...
Functional Components don't get Redux's connect performance optimizations which is a good reason to avoid them: https://github.com/rackt/redux/issues/1176#issuecomment-1670...
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...)
With regards to redux-thunk, have you taken a look at redux-saga[0]? Any thoughts?
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.
That said, Dan Abramov does seem to think it's a very intriguing approach, so it's worth keeping an eye on.
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.
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?
If you need an object (say to use it in something like Redux), you have to write a wrapper like so: https://gist.github.com/ebi/d186c4297c84d562aeae
isn't that div unnecessary?