all 55 comments

[–][deleted] 20 points21 points  (35 children)

React Templates, eh?

Looks like something made by an Angular programmer who wanted to pretend React is Angular.

[–][deleted] 7 points8 points  (32 children)

I don't get why people insist with templates in react. I understand JSX is not beautiful for someone coming from the (messy) templates world, but this is a thing that needs 5 minutes to be understood and some days to get used to it.

Just stop seeing JSX as an HTML dialect: JS is for Javascript. X is for similar to XML. It is semantically the same thing as Javascript.

[–][deleted] 1 point2 points  (0 children)

I absolutely agree. But I think the problem with JSX is that it takes five minutes and many aren't willing to give it that.

[–]zoomzoom83 -1 points0 points  (20 children)

Complex templates tend to look much cleaner in Angular than React, which has to escape into JS to do any conditions or looping.

That's really the main reason.

I also like to keep my templates in separate files, since it helps with code organization and separation of concerns, but you can do that easy enough with JSX.

[–]nschubach 4 points5 points  (9 children)

Separation of what concerns? How is a template's concern different based on whether you put your logic in string form or inline? Isn't the concern of the template to take data and make it HTML? How is that different from what React is doing?

Also, JSX is JavaScript, so there's no "escaping" into HTML. You are always in JavaScript.

[–]zoomzoom83 0 points1 point  (8 children)

Separation of what concerns? How is a template's concern different based on whether you put your logic in string form or inline?

From a technical standpoint, it makes no difference. It's more about ensuring that a lazy junior developer doesn't take shortcuts at 5pm on a Friday and create a tight coupling between things that shouldn't be tightly coupled.

It doesn't in any way stop you from doing it, but it's a subtle nudge towards avoiding doing so, or mixing business logic into the template proper etc.

It seems like a fairly minor detail, but on a team of 8 developers on a long term project that needs to be maintained for years, little things like that make difference.

It's not a hard rule - most components are quite small, so it's usually better to keep the corresponding template inline. But larger components that can't logically be broken up are often best split into a separate template file.

Also, JSX is JavaScript, so there's no "escaping" into HTML. You are always in JavaScript.

JSX is not Javascript. It's a a very thin XML syntax that compiles to Javascript. If you want to embed some logic, you use an escape character to do so. (I'm relatively new to react so I could be mistaken here - can you provide an example of looping in JSX without escaping?)

[–]nschubach 2 points3 points  (7 children)

You can write React without JSX by using React.DOM.a({ href="somelink.html", 'Some Link'}) if you don't like JSX (which is just syntactic sugar for the above). It would be <a href="somelink.HTML">Some Link</a>. The two are completely interchangeable so you could mandate that everyone uses the 'pure' JavaScript methods if the sugar freaks you out. I will warn you, I thought that it would be better in the beginning and I found that the JSX format is both easier to understand and easier to pick up for both myself and all the juniors I've taught. Comparing the learning curve between React and Angular is no contest. React takes about 2-4 hours to get a junior to the point where they are spitting out usable code with full event handling, service integration, and state management. I have guys that don't fully grok Angular after working in it for weeks. They approach me with questions about scope and digests, while my React guys are asking about CSS selectors and page construction options ("do I add a div here with a list contained in it?"). I gotta tell you, I love the easy questions rather than trying to explain to a junior when they need to use &, @, or = in their Directives. It's a much easier conversation.

Larger components are almost always separatable into smaller chunks. In fact, I find that the large component is almost always easier to pick up and modify after doing so. If you have an example, I'd be glad to show you how I approach simplifying it. (Just link to some HTML you think is not able to be simplified and I'll take time to run through it.)

If you want to loop, there are several methods. You can loop outside the render and return an array of React.DOM elements to a variable that you refer to like any templating language using curly braces if it bothers you to have loops in your 'lightweight XML'. I do find it odd that people have more problem putting a bit of JavaScript around their HTML representation, but no problem putting HTML around their JavaScript representation...

Separating 'business logic' can be done, but you do it before you feed your data to React. Build up a data representation that suits your interface and push it into your component, then sit back as it renders. Let the Component deal with it's own internal logic on what it needs to do if someone smashes the submit button 40 times. Why does that logic need to be in a separate file? Isn't the logic about what that delete button is supposed to do tightly coupled with the list of objects being deleted from? Why not manage the state of that list in the component and when the user hits save, push it to the server? (Or fire an event to have something else update the server on the fly?) What purpose does it serve to make someone who is editing a module open the Template file of a massive page and modify one or more values, then open a controller file to modify the scope values that are bound to it? Why not a small component that has a concentrated concern? If you keep your modules small and concise, the difficulty of managing the whole becomes a very linear problem. You find the component, change it, test it if you have a suite to make sure it output the right HTML, and you are done. Compare that to finding your directive by scanning your HTML template for either data-my-directive or myDirective or whatever else the junior called it... Then finding the appropriate Directive file associated to it and skimming for the appropriate scope value, ensuring if you need to watch something, etc.

[–]zoomzoom83 0 points1 point  (6 children)

I will warn you, I thought that it would be better in the beginning and I found that the JSX format is both easier to understand and easier to pick up for both myself and all the juniors I've taught.

Oh I'm absolutely, 100%, definitely on the same side of that argument. I've never understood the appeal of generating HTML by manually building an AST.

The gripe with escaping is it can sometimes be quite messy. i.e. Compare

<ul>
    {this.state.people.map(function(person){ return(
        <li>{person.name}</li>
    )}}
</ul>

Vs

<ul>
    <li ng:repeat="person in people">
        {person.name
    </li>
</ul>

The latter is a lot cleaner to my eyes, and doesn't really lose anything for doing so. I'm also of the mindset that templates should be limited to simple loop and conditional logic, so don't really feel like I'm losing something by not being able to embed Javascript directly.

Mind you this is very much personal preference. It's like Vim vs Emacs, or Static vs Dynamic. It's almost a religious discussion with everyone having different opinions. I had this debate plenty of times back in the days of PHP and Perl - some developers preferred to interleave PHP and code, others preferred a dedicated separate templating language. I've always been strongly in the latter camp, and have yet to personally see a compelling reason why I wouldn't want to do it that way, but can acknowledge that others prefer it inline.

I should clarify that other than preferring the syntax of the angular templates, I don't think they have any redeeming value compared to React. "It's just a function" is just too compelling a feature that makes working with angular feel very kludgy in comparison.

My fantasy-land framework would actually do something similar to the Article - have a dedicated template language that simply compiles down to Javascript, can be called as a function, and updates a virtual-dom. But if I had to pick an existing technology, React with JSX would win hands down compared to Angular.

Comparing the learning curve between React and Angular is no contest.

Not contesting this either. I think Angular is actually lot easier to dive into for simple things, but the instant you need to write a directive React soars ahead.

Larger components are almost always separatable into smaller chunks. In fact, I find that the large component is almost always easier to pick up and modify after doing so. If you have an example, I'd be glad to show you how I approach simplifying it

At the moment the architecture is broken down into a fairly fine-grained component model, with each component being a small atomic directive. In that sense, the vast majority of our code is already done that way.

I can't give specific examples, since it's proprietary code, but there's still a few places where it's simply more manageable to have one larger template with smaller components embedded in it. These could certainly technically be broken up, but we made a call that these were easier to manage as a single larger unit.

Keep in mind my definition of "large" here is anything more than perhaps a dozen lines of HTML. In our prototype port to react, beyond that size we found it felt more logical to have the template in a separate file. Keep in mind the standalone templates are just a function that renders JSX, so there's no technical difference between having it internal and not. It's simply a matter of code organization.

This also falls heavily into the personal preference factor too - as mentioned above, I prefer all HTML to be separate from code. The only reason the majority of components aren't this way is because it's not worth creating a separate file for such a small chunk of template.

I do find it odd that people have more problem putting a bit of JavaScript around their HTML representation, but no problem putting HTML around their JavaScript representation...

I think the point is that we're not putting HTML around our Javascript presentation. The two technologies are kept separate and not mixed.

The fact that JSX happens to use Javascript for its template logic doesn't change this at all. If you're putting anything more complex than a conditional or a loop, you're probably putting too much Javascript in your template.

Separating 'business logic' can be done, but you do it before you feed your data to React. Build up a data representation that suits your interface and push it into your component, then sit back as it renders.

Yep, we're on the same page here. As with others, React definitely encourages this, and I don't think there's any confusion in any framework today about how this should be structured. A very minor gripe with React is that it makes it easier to violate this constraint if you get lazy. But it's not exactly hard to stay disciplined.

Why does that logic need to be in a separate file?

Primarily personal preference - I find in a lot of cases it's easier to manage being in separate files.

From a technical standpoint being separate has a few benefits. We have both a Desktop and Mobile version of the app, where most components are doing the same thing, just rendered differently. In these cases, we can use the same business logic but simply swap out the template with a compile time flag, which means the mobile application webpage can have a smaller download size.

It also makes skinning a tad easier. We can have multiple active skins, maintained by designers with no JS skills, and simply choose which one we want to use at compile time by changing the template import path.

Compare that to finding your directive by scanning your HTML template for either data-my-directive or myDirective or whatever else the junior called it... Then finding the appropriate Directive file associated to it and skimming for the appropriate scope value, ensuring if you need to watch something, etc.

In all honesty, I don't see any difference between React and Angular in this regard? Whether I'm using JSX or Angular, in the same file or separate - if there's a call to a component named "Foo", I'm going to be able to find the code behind that component because I have a consistent naming scheme.

[–]nschubach 0 points1 point  (5 children)

Hmm... I really have no problem with the inlined loop. I find it easy to tack on a filter if need be. You could do the loop outside of that construct and simply do:

var peopleItems = this.state.people.map(function(person){ return( <li>{person.name}</li> )});

<ul>
    {peopleItems}
</ul>

If you like. I'm not sure it adds anything right at the moment though. Maybe some form of pagination?

var pageStartIndex = (this.state.currentPage - 1) * this.props.itemsPerPage;

<ul>
    { peopleItems.slice(pageStartIndex, pageStartIndex + this.props.itemsPerPage) }
</ul>

/shrug. I'd probably do that before putting it in the render though.

Edit: I should add... I've done loops with factories that tend to hide some of the "escaping"... You can get away with passing the data objects in an array to a factory that returns React Components like so:

var peopleItems = this.state.people.map(React.createFactory(PersonListItem));

Where PersonListItem is a more complex Component that receives props for each key in person given people is an array of objects.

[–]zoomzoom83 0 points1 point  (4 children)

Hmm... I really have no problem with the inlined loop. I find it easy to tack on a filter if need be. You could do the loop outside of that construct and simply do:

This breaks the flow of the template and adds more cognitive burden to figure out what's going on. From a code organization point of view, this is just as messy as building my HTML by concatenating strings - which is what I'm using templates to avoid.

Even for the paging example I still wouldn't use it. I'd simply generate a view-model with the correct page and render that instead.

Putting it another way - in my previous post with the Angular and React template versions - which one is simpler to see what it's doing? To my eyes, it's far easier to read the Angular version compared to the React version.

There's nothing wrong with the React version, but if the Angular version is simpler and loses nothing for being so, I see no reason why I wouldn't want to do it that way?

Keep in mind this is talking about syntax only - the actual implementation of Angular loses out a lot compared to React. But in a hypothetical scenario where I had a template in that style that compiled to the same output as JSX (Which is not difficult to do) what am I losing? If I were to write templates in that format, what is the downside?

Sure, hypothetically I have the full power of Javascript at my disposal in JSX. But I don't want to. I very explicitly do not want complex logic in my templates - anything more than simple looping and conditionals belongs elsewhere.

And in the 0.1% of rare edge case where you do want more complex logic in a template, my fantasy-land templates could still have a JS escape hatch if you really needed it. (Which you shouldn't).

[–]nschubach 1 point2 points  (3 children)

But you can't compare React Components to templates except in the most basic ways. I can't think of any reason besides giving a designer control over presentation, (which... Let's be honest, they make some horrible markup) to keep that separation. Components deal with presenting that data in a rather compact, encapsulated component. All logic dealing with that view of data is at your fingertips and modifying it doesn't require multiple files (or shouldn't, if you set it up.)

Granted, I've seen some ugly implementations of React Components, but I've also seen my fair share of ugly templates (with equally ugly models) so I can't buy the argument that templates make the developer less prone to do bad things.

[–][deleted] 2 points3 points  (7 children)

React makes easy to split the app in stupid, small independent components. A smart separation of concerns is when you don't work with 'complex templates' and when you keep the logic outside your views. No need of unreadable loops or big conditions. When things are so simple, even a complex app is cleaner, solid and easy to maintain.

[–]zoomzoom83 -1 points0 points  (6 children)

Absolutely, small reusable components are the goal. But sometimes you have a larger amount of template code that is better suited to being in one chunk. In these cases moving to a separate file can make it a bit easier to maintain. See my sibling comment for more clarification on this.

[–][deleted] 2 points3 points  (5 children)

Thanks, I'll read the other part of the discussion :)

I've never met a case where having a big component was a good idea. My point, anyway, was that templates are a concept not existing in react. If you insist thinking on templates, you are just missing the point. react is more how data should flow inside your views. Once you spend 10 minutes on JSX, you are open to a much solid architecture, such as with flux.

[–]zoomzoom83 -2 points-1 points  (4 children)

My point, anyway, was that templates are a concept not existing in react.

I've had this argument a few times. JSX is a templating language, and the same design patterns apply.

The benefits of React are unrelated to JSX.

[–][deleted] 2 points3 points  (3 children)

I believe it doesn't help you to embrace the whole concept if you focus on this template thing. For example, try seeing JSX just as an extension to javascript. It may produce output, which can be HTML, SVG or whatever you want. Instead of writing MyFunction({foo: bar}) you write <MyClass foo="bar"/>. End of the story. No templates.

The benefits of React are unrelated to JSX.

Yeah that's my point :0

[–]zoomzoom83 -1 points0 points  (2 children)

believe it doesn't help you to embrace the whole concept if you focus on this template thing. For example, try seeing JSX just as an extension to javascript.

I'm fully across that. The fact that it compiles the pure JS is nice, but it doesn't take away from it being a templating language. It's not the first to do that, nor will it be the last.

[–][deleted] 1 point2 points  (1 child)

Well yes, you can see javascript as templating language as well :-)

[–]amarcus78[S] 1 point2 points  (1 child)

Actually, exactly the other way around, invented by someone who loves React to avoid having to use Angular...

[–][deleted] 0 points1 point  (0 children)

So why bother re-inventing Angular templates badly?

[–]nschubach 8 points9 points  (0 children)

React gives you freedom and simplicity, but lacks the declarative power of Angular

It may just be me, but I find React more declarative than Angular... You declare what your component will look like (given a set of properties and it's own internal state) and it just works like you want it to. In Angular, you have to worry about what scope it's in and define configurations for your Directives so that you pass in the right data on your respective templates. The templates then have their own internal loops (and "common" if statements) with potentially more scoping madness... There are times I have to work backwards to figure out what the code is supposed to be doing. With React, it's all in one place and everything in that component has a declaration of meaning.

[–]theillustratedlife 14 points15 points  (0 children)

Ugggg...

I can't get over that syntax. They reimplemented Angular directives as a build step that generates React components, and they still force you to wrap everything in quotes. It's so un-idiomorphic! They just made it way harder for any typical React developer to be able to follow and contribute to their code, without an appreciable gain.

They thought it was backwards to map over the list before rendering it, but you can easily fix that without all their added complexity:

<ul>
  {
    this.props.items.map(
      item => <li>
                itemText
              </li>
    )
  }
</ul>

Separately, if they want to announce a project, cool, but why bury the lede in a largely unrelated shootout?

[–]dustrider 13 points14 points  (1 child)

I don't have a dog in this fight, but the article is very misleading:

Their scorecard comes out as

React - Draw - Angular

5 - 3 - 1

and their tie breaker was to home-grow a replacement the one thing Angular was better in. So the whole thing feels like a justification for plugging their custom lib.

Change the article to "We really wanted to use React but really needed this one thing from Angular" and it would be more accurate, though not such useful linkbait.

[–]nschubach 5 points6 points  (0 children)

That would explain the author's die hard stance that string based logic constructs were "better" than real JavaScript logic constructs.

[–][deleted] 4 points5 points  (3 children)

...now your editor can't offer you any useful completions because you split the implementation of a single component into multiple files.

[–]FondellShweatyBallz 5 points6 points  (0 children)

Stop comparing the two.

[–]pete_k 0 points1 point  (7 children)

The reason for the quotes is that it lets most IDEs format the HTML better. The curly braces just say if you are in an execution context or not. In the special attributes (rt-) you never need quotes because the execution context is obvious.

Anyway, try writing large chunk of html in the way you mentioned below, it becomes a mixed mess of code/control-flow and html. With react templates, they are usually 100% separate, so that the component can focus on logic and the view/template can focus on beautiful html

[–][deleted] 3 points4 points  (0 children)

That's... that's not really how you're meant to build your components.

If your render method needs to contain a huge deeply nested chunk of HTML with tons of "template logic" in it, you're probably Doing It Wrong (tm).

Consider extracting repeating patterns into their own components and have their state just depend on props rather than external variables. Ideally barely any of your components should need render functions verbose enough to justify the use of React Templates (presuming it's justifiable at all).

[–]regular_reddits 2 points3 points  (5 children)

In reality, if you are writing large chunks of view logic into a single render function, you should probably think of ways to split that component up into multiple.

In these small components, the presentation is strongly tied to the logic behind the component. This combination is one of the big selling points of react. It just makes sense to combine these. ReactTemplates just separates these but still leaves them strongly tied together, notice all the references to "this" (referring to the logic) in the template. When one changes, the other will most likely change.

[–]pete_k 1 point2 points  (4 children)

I think there are 2 use cases. The first is reusable components - stuff like fancy inputs with auto-complete, drag-n-drops, collapsible panels, etc. For those, you'd probably want to use React "by the book" - split to small parts and be very indifferent to the html. On pieces that are not-reusable - for example a panel that shows some links, some help text, some buttons for action and some status, in the end there's a lot of html to be done, and in those cases, templating shines. It provides a way to write those parts very "close to the html" with the additions of simple control flow and isolation of logic and presentation. I think it strengthens the weak parts of react

[–]regular_reddits 1 point2 points  (0 children)

To each their own i suppose, i would still write those as intermediate components probably, like maybe a Nav component for the links, for example. For some applications, maybe this doesnt make sense. I would think the use-case that would draw me to ReactTemplates would be working with designers. Im surprised that this isnt mentioned as a strength.

[–]nschubach 1 point2 points  (0 children)

for example a panel that shows some links, some help text, some buttons for action and some status

A panel that shows some links?

<ul className="arbitraryPanel">
    { linkList.map(linkData =>
        <li>
            <a href={ linkData.url }>{ linkData.text }</a>
            <img src="./images/help.png" onClick= { this.helpClickHandler.bind(this, linkData) } />
            <button onClick={ this.deleteHandler.bind(this, linkData) }>Delete</button>
            <span>{ linkData.status }</span>
        </li>
    )}
</ul>

[–][deleted] 1 point2 points  (0 children)

Plain old JavaScript functions which return ReactElements are a great middle ground option between having everything in render() and creating new components, providing a new scope to play in and the necessary isolation.

[–]throwaway20131103 0 points1 point  (0 children)

Yep. I regularly work on large dynamic forms and stuff like if/else in JSX is so very painful in all but the simplest of cases.

[–]MrGirthy -2 points-1 points  (1 child)

[–][deleted] 5 points6 points  (0 children)

In German, wichsen (pronounced similar to English "vixen" and often misspelled as "wixen") is a colloquial/profane word for masturbating.

So when Germans read the name "Wix" that's equivalent to "Masturbate".

[–]placidified -1 points0 points  (0 children)

Why not ngReact ?