Hacker News new | past | comments | ask | show | jobs | submit login

I remember when I looked into React that I was basically writing HTML templates into javascript code. Are there ways around doing that now with React? Because I find that to be a pretty big affront to separation of concerns

You don't have to use JSX. You can use React.DOM directly or use react-hyperscript as a shorthand method for React.DOM

Also pay attention to the new createFactory method which aims to make it easy to separate your changing HTML from the static HTML (which you would have previously used a templating library for)

My recommendation is to not use JSX ever since it breaks a lot of your tooling. The first impression people get is that "Hey this makes my code easier to read", but that is only because JSX introduces the problem that it attempts to solve.

Basically most HTML structures are 80% unchanging and 20% changing (the reason we use templates in the first place). React.DOM was a pain previously because you'd define a complicated HTML structure in Javascript, which isn't really any harder or more complex, but then you'd have all this code that was never changing distracting you from the code that was changing (i.e. your app behavior). JSX fixed this problem by turning all the static bits to html like templates do so it was visually easy to separate from your behavior code. This was the wrong solution because it's over engineered and breaks compatibility with a lot of things.

createFactory essentially allows you to "partially apply" the static parts and get a function that only needs to deal with the dynamic parts (like compiled template functions but for virtual DOM)

Anyways, check out the following links:



Separation of concerns is different from separation of technologies. For more details, view Pete Hunt's excellent talk at http://2013.jsconf.eu/speakers/pete-hunt-react-rethinking-be...

The question is whether those concerns need separating. I've come to believe that the price to pay for that "separation" is too big and ends up being a re-implementation of shared scope (see angular's $scope)

Likewise the price to pay is yet another template language. ReactJS uses JavaScript as its template language. No more exporting filters, weird looping and conditional constructs. Just use Javascript. It just makes sense.

Having used React for a year now, I have long concluded that React doesn't violate any separation of concerns at all.

React implements UI views and controllers. You write views that know how to render themselves, and then you write views that control them; the latter type of view fulfills the role of the classical MVC controller.

For example, consider how Cocoa works. It's a classical MVC framework: You have a view controller, which mediates between data and views. The controller doesn't know how to render anything, but it listens to data modifications, and sends update commands to the views; it also listens to changes to views and propagates those changes to the data model. (You can also let Cocoa Bindings do it for you, for the most part.)

In a single app, you typically end up with many such controllers, typically one per window, and controllers can reference each other to facilitate communication; also, there are often controllers that individually control just a single view, because it's easier to encapsulate reusable components that way. For example, if you need a text field that autocompletes, you could subclass NSTextField and build this special behaviour into the view itself, but it's cleaner to create a controller that can bind to any normal NSTextView.

In React, you have the same distribution of controllers (some handling big, multi-view layouts, some targeting discrete views), but the controller actually takes part in the view hierarchy: A controller has views as its children. It may not even use DOM elements, but consist entirely of custom view components. And it does exactly the same stuff as a controller would. For example, it may contain this:

      <TextField label='Name' minLength={3} ref='nameField'
      <NumericField label='Age' min={0} ref='ageField'
In this example, TextField and NumericField would be generic view components, just like the standard Cocoa views; the controller wouldn't be doing anything view-related like working with the DOM, but it would mediate between the data model and the child views that it controls.

This is very much like building out a form in Interface Builder and connecting the actual controls to variables using IBOutlets. In fact, I would argue that there is hardly any distinction at all. The difference is that the UI is declared in the controller. And why not? Interface Builder is separate, and keeps its view data stored separately, because a WYSIWYG editor can't touch code. (Actually, Delphi showed that it was possible, but that's another story.)

The fact that there is a separation isn't actually useful to anyone. You generally cannot edit the view layout without breaking code, and you can't edit the code without breaking the view: They have to be maintained completely in sync with each other. So you might as well just keep the view layout in the same file as the controller. Which is what React does.

>The fact that there is a separation isn't actually useful to anyone. You generally cannot edit the view layout without breaking code, and you can't edit the code without breaking the view: They have to be maintained completely in sync with each other

As someone working on a team that practices a good amount of separation of concerns, this is patently false. This is more dependent on how good your template language is than anything, but this separation helps to assure that we're not introducing new bugs or the like.

The main arguments for React along what you're saying is that people seem to abuse the "view model" concept. It's rarely as necessary as people seem to want to make it (though again, dependent on template language).

The fact that you're able to do it doesn't mean it's a good idea. On the contrary, I believe it's a bad idea.

It has nothing to do with how good your template language is. It's simply that a controller's main controller (not talking about partials here) has an implicit dependency on the controller, and the controller has a dependency on the template. Unlike, say, data models, the relationship is not unidirectional.

But really, what is this separation for? What does it gain us? We generally separate stuff out into declarations and files because it gains us modularity ("separation of concerns") and reusability. Data models are constantly reused, for example, as are views. But that one template belonging exclusively to the controller isn't reusable. It's separated out for no particular reason other than the fact that, historically, it has been expressed in a different language and must be parsed and "compiled" separately, so it has not been about "concerns" but about implementation details.

React removes that step, and because the template is unequivocally tied to the controller, there is nothing gained by separating them. The point of React is that the "template" is the component. The component's rendering is intimately tied to how its internal state and data model is wired up because the one half wouldn't work without the other, and vice versa.

(As an aside, in a well-designed, pure component, there is little state and the component is mostly template, anyway.)

(As an aside, most template languages don't even let you validate a template's inputs — that is, declaring that it requires specific named inputs and what their types/structure are. No idea why, seems pretty obvious defensive functionality to me. But React does this.)

> Interface Builder is separate, and keeps its view data stored separately, because a WYSIWYG editor can't touch code. (Actually, Delphi showed that it was possible, but that's another story.)

Oooh, do tell!

Delphi automatically synchronized itself with your code. They called this "two-way editing" and it was magical, and worked wonderfully.

Let's say you created a form, which in Delphi parlance was a surface that could inhabit controls, typically an actual application window. You would get this empty window:


You would also automatically get a source file containing the class definition for that form, roughly corresponding to a window controller class in Cococa. This class would be completely empty, mind; no init code needed or anything:


(The GUI layout would live in a separate binary "form file" you never needed to edit directly. This file contained serialized objects that you could read and write in code, similar to OS X bundles, except more easily extensible.)

This class would be, by virtue of having the same base file name, automatically linked up with the corresponding form, so you could quickly switch between code and UI.

Then if you added a button the form, Delphi would automatically add a private member variable declaration "FButton1: TButton" to your class definition, as glimpsed here:


The framework would know, from the GUI definition, that FButton1 was that button. You could edit it and move it around in your code, and it would still be bound correctly.

Same thing with event handlers: If you went into the button's inspector and double-clicked on the "click" handler, it created the method for you, and placed the cursor in the right place so you could immediately fill it out with code.

This system made developers insanely productive, because the "boilerplate interactions" were reduced to almost nothing, and all the work was actual work. No "IBOutlet" stuff needed, no manually connecting the variable to the right thing in the GUI builder, and very little setup.

A few more brilliant, deceptively minor details made this even more magical. First, the form you edited was truly "live". Delphi actually rendered real controls in the editor. If you created a control that did custom rendering, it would render like that in the GUI editor, live. Interface Builder sort of does this, but not quite, and custom controls are a pain and apparently no longer supported.

The second thing was the object inspector:


Interface Builder has a very poor one; Delphi's felt natural. Every property exposed by a control would be visible there through reflection: Delphi would actually parse properties out of your code. It supported structured properties, so if something was a TFont, it expanded into sub-properties for font name, font size and so on.

If you created a new class TGradientButton or something, and exposed two properties FromColor and ToColor, they would show up in the object inspector, automatically, and since these properties would be something like TColor, it would know to display an RGB widget for them.

You could also register custom object inspector behaviour, so that, instead of FromColor/ToColor, perhaps there was only one property "Gradient" of type TGradient. Your custom object inspector thingy could then render a gradient editor for that property.

XCode + Interface Builder is about 10% of what Delphi was. I say "was", it still exists, but I haven't touched it since around 2000-2001. It's insane that Delphi 1.0 in 1995 was more powerful than XCode + Interface Builder today.

(I suppose it lives on in the Visual.NET tools; after creating Delphi, Anders Hejlsberg joined Microsoft and created C#. But I haven't used any of it.)

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact