It's comments like these while people don't hire anyone over 30. Rather than provide thoughtful critique of the platform the response is "This looks like something I saw 20 years ago and it didn't work then so it won't work now, I'm not even going to look at it!"
Speaking as someone who is over 30... before you criticize something, understand it. For example, this code is nothing like PHP spaghetti code for reasons I listed in other comments among others I'm sure I didn't think of.
I see it very often. People like "we did this 30 years ago. I guess what is old is new again. Hahaha" But I've lived through it... like many of you... I've gone from CGI scripts written in C++ when you couldn't even guarantee a browser had Javascript to PHP, to Ruby, etc etc etc, blah blah blah. But after all that, and a Computer Science degree, I gave React an honest look and while it's not perfect. It is worth a look.
React runs on the client. It runs the logic needed on the client. And there has always been some logic required on the client, otherwise you end up refreshing the screen for every.single.validation. which is a total PITA.
Given that there's some logic running on the client, then maybe running more of it there would be a good thing. This is the principle behind SPA's after all, and they've turned out to be a Good Thing generally. Not suitable for every use case, mind. So do we then need a separate Logic Layer for logic that isn't to do with Presentation? Where do we draw that line given that the whole thing is running on the client? How do we keep the thing clean and stop bits of logic being run on random button events?
React makes perfect sense when you look at it as an answer to the problem of "how do I add logic to my presentation layer and not end up in a mess of spaghetti code?"
Also, having JSX in my JS is much easier to deal with than remembering some abstract DSL for how to iterate through children in a template language. It's no more goofy.
Now several years later I'm inheriting Nodejs and [flavor of the month] Javascript framework projects from coworkers that look like the PHP video sharing site I wrote in 10th grade using XAMPP.
I feel like I have (or everyone else has) contracted some sort of amnesia. Didn't we already hash this out guys?
It is close to a view in a MVC framework than true old-school spagetti code.
But unlike a view component in an MVC framework the stateful components can update themselves automatically when data changes much more elegantly than they could in older systems.
Granted some people write React and include business logic in their components but you're not really supposed to do it that way.
If I'm working on a component level, it's already granular enough where I can easily understand the changes that need to be made and I can just update those DOM elements myself (e.g. Oh, I should add this class here and update my shopping cart total).
The DOM diffing for small components seems so... heavy handed. "Don't worry React, I got this.."
If you don't do DOM diffing for small components then you have to keep control of the whole logic state AND view state of your app.
Complete diffing allows for automatic one way bindings and easier to reason UIs.
It's like functional programming.
In your shopping cart example, say the project manager decides they want to display how may of an item you have in your cart next to the item in the catalog. Then a feature is added to remove items from any page by having a dropdown on the cart logo.
So is it the responsibility of the person writing the cart dropdown to update the catalog listing or the responsibility of the person writing the catalog listing to know about the drop-down?
In React you only need to bind to the data. If the data changes and your DOM then changes as a result then you update. You don't need to know why or how it changed.
As far as the virtual DOM being perhaps heavy handed. It is a performance optimization and not really a core concept. The React team found it was faster to update only the parts of the DOM that changed rather than redraw the entire screen and came up with a clever way to do that without having to know the implementation details of each component.
Contrast that with the naive approach (using innerHTML) which would make even a "update the character count every time a key is pressed" UI grind to a halt.
React means composable components, the browser implementation uses DOM diffing.
for a component, why do I need the virtual dom diffing?
React allows you to build relatively large and complicated DOM trees by composing smaller components, and it is designed so you can then (re)render the entire tree as a single operation when any relevant underlying state changes, without having to manage (re)rendering each individual component within that tree manually.
This is useful because now you only need to define one absolute way to render from a given set of underlying data. You no longer need to give a relative specification for all possible transitions from one state to another, which can be a huge reduction in complexity and edge cases if you’re working on a large, complicated UI.
However, other things being equal, rerendering your entire DOM tree on the slightest change in the underlying data would become painfully slow for any system that isn’t very small. That is partly because there are costs to regenerating the DOM tree itself, as with any template-based system. However, the tightest bottleneck in today’s browsers is usually the consequential costs that result from updating the DOM in terms of regenerating layout and so on.
The virtual DOM diffing is essentially a performance optimisation that lets you mitigate those consequential costs, because now only the parts of the DOM that actually change as a result of changes in the underlying data will lead to rerendering in the browser and the costs that incurs. In other words, virtual DOM diffing isn’t the point of React, declarative/absolute rendering is, but the former is what makes the latter fast enough to be viable.
As an aside, React’s answer to the other half of the performance problem, the cost of regenerating the entire DOM tree, is the `shouldComponentUpdate` function. That lets components, including child components deep within a large tree, perform any quick tests they can to determine whether their rendered output will actually change, and to skip the rerendering if not.
That leads on to various other ideas that have become popular in connection with React, such as using immutable data models for the underlying data. With immutable underlying data, a shallow comparison between a couple of object references that can be performed in moments acts as a “dirty check”.
However, you don’t have to use React in that way. Some people are wary of relying too much on `shouldComponentUpdate`, which inherently violates the “single source of truth” principle and risks introducing bugs if its assumptions differ from those of the same component’s `render` method. Others find the arguments for building your entire data store around immutable objects, which itself carries a hefty performance overhead, less compelling.
There are certainly other reasonable architectures you could choose for supplying the underlying data to React components and triggering rerendering when that data changes, including more traditional designs where view components observe the underlying data model in some way and trigger their own rerendering on any relevant change. Going down this path is effectively using React as a reasonably efficient and composable template rendering engine, so you can still have the advantages of absolute rendering logic, and you bypass some of the potential performance problems caused by doing large-scale rerenders with React, but in return you take back some of the responsibility to set up explicit dependencies between your view components and the data they depend on. As ever, there are trade-offs, and usually there will be multiple quite different designs that will do a decent job as long as you understand their pros and cons.
We should always be wary of applying skyscraper building techniques when building a house or a shed.
I honestly bet that 99.99% of people who read Hacker News could write their applications with a drop of jQuery and some basic ES6 code.
I have nothing bad to say about these frameworks, more caution that we don't apply techniques needed at scale to small scale products.
It's fashion, like anything else.
Unfortunately I can't babysit every other team and have occasionally inherited some real abominations. Often times it has been worth spending the ~week in man hours to immediately rewrite them to avoid the constant time suck of maintaining spaghetti code down the line.
Often they are a kernel of simple functionality buried in thousands of lines of code smeared across a random assortment of files that can actually be replaced fairly simply once you've sussed out what they're actually supposed to be doing.
Maybe we're backtracking on the idiocy we started on around PHP times? The whole "separation of concerns" thing that went to such extremes as to become a cargo cult? I offer two observations:
- presentation is often very much content at the same time (that's why websites end up cluttered with divs that have no semantic meaning and serve no other purpose than being CSS hooks)
- separation of concerns was about not putting business code in views, not about having views without any code; you need code to drive views (and yes, template languages are Turing-complete, so they count as code too)
Writing as someone comfortably over 30, I don’t see the problem here (edit: meaning having something that looks like HTML and something that looks like JS in the same place).
If you need to generate content dynamically for a web page based on some underlying business logic and data, you need some sort of rendering logic that determines how to fill in the blanks in your generic pattern using your current specific information. This has been true for every template system and framework since forever.
Personally, I don’t much like putting the logic right there in the JSX, as the `map` does in the tweeted example. I think one of the nicer things about the way React and JSX work is that you do have the full power of JS to write your rendering logic, and you can build up a part of the rendered output separately and then compose the overall output from the individual parts without needing to put a lot of extra logic in there. But that’s just my personal preference, and others might reasonably disagree.
The challenges with building larger applications in PHP — or in JavaScript, for that matter — have more often been about not having good tools in the language to build cleanly separated, modular designs. That side of things has improved somewhat with time, and will probably always be less than ideal because of the legacy baggage these languages now carry, but in any case the big problems were never really about an artificial separation of HTML, CSS and JS, and including JSX within JS code when using React is little different to embedding conditional logic in any other template language used by any other programming language or library.
It does look similar but it is night and day different beyond the superficial appearance. Are you actually trying to say that the in-browser experience in web apps from 15 years ago were in the same ballpark as even simple single page javascript apps from today? That is laughable. So something must be different right?? Derisive condescending comments like yours prevent the conversation from figuring out what the positive is and ultimately keep the conversation stuck in the all too common and boring whining about javascript which has infected HN.
Yes I'm bitter that the same errors we made with desktop apps in the 90's (and possibly earlier) are being repeated.
> Are you actually trying to say that the in-browser experience in web apps from 15 years ago were in the same ballpark as even simple single page javascript apps from today?
Yes. The biggest difference is the amount of postbacks, the state handling has moved client side.
This is emphatically NOT the same as the desktop apps in the 90's.
Its like the payday loan of technical debt.
So I think I can say with some confidence that everything you have written is completely nonsense.
> It is amazing how much react resembles php and classic asp from 15 years ago.
Yes, it's amazing how it's nothing at all alike.
And I've been around before PHP was a thing.
I realized a couple months ago how incredibly similar JSX is to Cold Fusion - At least CF4. It's nearly identical in some respects.
Now, there are standards like SOAP, etc... In the end, JSON and some clear docs for an API is usually easier to reason with than any of the boatloads of cruft that came along with XML. Not to mention the much larger transmission size.
In judging whether something should be represented as element text or as attribute, ask yourself whether that something is content or metadata. In a context where this distinction doesn't make sense, markup (SGML, XML, HTML) probably doesn't make sense either.
Markup isn't and never was intended for representing arbitrary data - it is for representing text with optional markup, and is designed for end-users and content authors, not necessarily web developers.
As for representing XML in code, there was E4X which allowed you to represent XML literals in Javascript (Firefox and rhino had it a couple years ago, but it kindof wasn't convincing). Keep in mind that Javascript was invented as a language to manipulate a DOM in the first place, so there you have your canonical representation of markup in Javascript.
Sure you can represent objects, ie. a memory dump of a running program, as XML, but what's the point?
IMO It just needs to be given some consideration before rejecting as old bloated piece of crap.
XML translates great to an object tree in many object oriented language.
<foo bar="1">
<yo />
Hello
</foo>
new foo(new yo(), "hello", bar = 1)
Which is why it's so great to describe documents and static UIs.I agree though that it's not a great choice for a REST API.
<foo yo="true">
<bar>1</bar>
<value>Hello</value>
</foo>
Could represent the same object structure, for example. JSON is a pretty clean mapping to objects/properties/arrays, with less chance of confusion, or alternate interpretations.Whether something is inside an element or is a property of said element has important semantical meaning. But not just that, with XML you can implicitly represent ordering, whitespace and type information with much less boilerplate.
So the argument for JSON is basically boils down to: "Javascript has horrible type support and doesn't support OOP. JSON models that experience better."
unless you are using some lisp-2 dialect
I have arguments against that but I'll keep them to myself because your sentence isn't really relevant to the original discussion.
If you’re talking about the `todos` list in the tweeted example, I’m afraid you’ve been successfully trolled. In non-toy code, you’d typically hold the underlying state in a separate part of your system rather than the rendering React component, as with any other sanely designed UI. That data would be passed into the React component via `props` so it knew what to render, and the callback function to handle a form submission would also be passed in via `props`, and the React component would have no dependencies on anything else in your system. It’s actually one of the simplest, cleanest and most completely specified interfaces of any modern JS UI library or framework, in my experience.
It is true that a React component can also hold its own state and can use that data in addition to the supplied props when rendering. However, that state is normally reserved for UI-related data that isn’t part of the underlying data model, such as keeping track of a selected item or which page is currently active on a paginated table view. Toy examples like to-do lists sometimes use React component state to hold more general data, because that is simpler in a trivial demonstration than writing separate MVC components or the equivalent, but that’s not how you write idiomatic React code in production systems, and it never has been.
If you want to experiment, my advice would be to start by just using React as a template-rendering system that lets you conveniently build larger and more complex components by composing smaller and simpler ones and that can automatically change whatever is already in your DOM to whatever new DOM content you come up with when rerendering. At this stage, you can take advantage of React’s greatest strengths, but you don't need any bells and whistles like Redux or Immutable or MobX or whatever other state management libraries you’ve come across.
One thing I would recommend right from the start is storing your application state somewhere outside your React components, even if it’s just in plain JavaScript objects. When you’re ready to render a DOM tree, pass that data into the top-level React component via props. Have that top-level component in turn pass any relevant part(s) of its input data to any child component(s) that need that data for their own rendering.
Likewise, I would recommend defining the functions to handle any interesting events outside your React components. You can then pass any callbacks you might need in via props on your components as well.
If you try that sort of design out a few times with non-trivial apps, you’ll soon start to see common patterns where introducing other tools might be helpful, and at that point you’ll have a better understanding of what some of those other libraries do and which combinations of related libraries might be useful for your particular needs.
I’d like to repeat here that React doesn’t require that you use that particular style of architecture, and there are plenty of reasonable alternatives. However, hopefully those examples should suffice to demonstrate that separation of underlying state from UI rendering and responding to interactions makes as much sense with React as in other contexts and is widely employed in practice.
Unfortunately, the example from the tweet really does: the storage and manipulation of the to-do list itself is right there, mixed in with the rendering component. I think it’s a bad example of how to write UI code using React, because while it’s concise and it works, the techniques it shows lack flexibility and don’t scale well, and they’re not how you’d actually write a larger app’s UI that renders using React.