Feedback Appreciated: JSX Templates

Reading the various Blaze vs React threads here, it seems like one of the most common concerns preventing people from switching to React is the way it mixes HTML and JS in the same file. This is bad from a separation of concerns point of view (if you care about such things), but more practically speaking also makes it a bit more risky for non-programmers (i.e. front-end designers) to modify your component code.

A great solution to this is functional stateless components. But you’re still adding a bit of JavaScript code in there for every component (specifically, the function declaration and return statement).

So I had this idea for a Meteor package to enable getting rid of this boilerplate, and making React components more compatible with designer/developer workflows. I’m not sure if it’s a good idea or not, so I would love some feedback from both the React and Blaze crowd. Here’s more details:

4 Likes

I added React to a two year old Rails project we have. Having stateless components was good for us, because we grabbed that data from our controllers, as opposed to using something like Ajax calls within the components themselves. We just passed in pure strings, numbers and arrays.

However, I believe that Meteor being reactive by default, it makes sense to use that reactivity and avoid having having a wrapping container in charge of getting the data unless you really understand why you’re adding a container.

I agree, having stateless components -does- make it easier for designers to create components in a vacuum! That’s a major win.


For our projects, we’re moving towards containers because it allows my brother to design components using raw data. Then I can just plug in the actual data, and there you go, all done. ReactMeteorData detects a change, and re-runs the render() down into my stateless component and presto.

To be honest I’ve just been following the best practices recommended by Mantra. I agree not every single app will require you to split components into smart/dumb sub-components, but overall I think it does make your app more flexible, and potentially even less dependant on React itself.

1 Like

100% true. The question for you and your team is how far up do you want to architect things.

For our case, it makes sense. My brother can create components without me blocking him, and I can tie those in when I get to them. It’s pretty neat. :thumbsup:

I suppose my question(s) are this:

a) How are functional stateless components better than BlazeReact?
b) How can BlazeReact be improved using functional stateless components?

Not having side effects is a good thing. Yay! Stateless. No side effects. But compared to having a library that supports Spacebars syntax vs having a library that has no side effects, we’ll take the Spacebars syntax any day of the week. We deal with side-effects all the time, and know how to manage it. The Spacebars syntax however… represents tens of thousands of lines of codes and many dozens of packages and apps.

1 Like

I don’t see how Meteors reactivity stops you from isolating state in React?

I’m curious though, how do you test Blaze or BlazeReact components?

In React you can use ReactTestUtils to write tests for your components. Having them be ‘dumb’ components also makes them easier to test.

For example, our <TextConfirmButton /> component.

var TestUtils = React.addons.TestUtils;

describe('TextConfirmButton', function () {
  it('starts with confirm button disabled', function () {
    var onConfirmClick = function() {
      console.log("Confirm click");
    }

    var textConfirmButton = TestUtils.renderIntoDocument(
      <TextConfirmButton confirmText="example" onConfirmClick={this.onConfirmClick} />
    );

    var textConfirmButtonNode = TestUtils.findRenderedDOMComponentWithTag(textConfirmButton, 'button');
    expect(textConfirmButtonNode.disabled).toEqual(true);
  });

  it('enables button when text matches', function () {
    var onConfirmClick = function() {
      console.log("Confirm click");
    }

    var textConfirmButton = TestUtils.renderIntoDocument(
      <TextConfirmButton confirmText="example" onConfirmClick={this.onConfirmClick} />
    );

    var textConfirmButtonNode = TestUtils.findRenderedDOMComponentWithTag(textConfirmButton, 'button');
    expect(textConfirmButtonNode.disabled).toEqual(true);

    var inputNode = TestUtils.findRenderedDOMComponentWithTag(textConfirmButton, 'input');
    inputNode.value = "example";
    TestUtils.Simulate.change(inputNode);
    expect(textConfirmButtonNode.disabled).toEqual(false);
  });
});

Well I feel like supporting Spacebars syntax is a whole other debate, and the React community as a whole seems pretty anti-template. I mean, there are existing React templating solutions out there but I don’t think they’ve been adopted by React leaders.

So this would be more of a way to meet people halfway and get some of the benefits of templates (separate files, easier syntax highlighting, minimal logic in components, etc.) without actually adding a templating language.

Then I’d recommend positioning JSX Templates as the step after BlazeReact. That’s the refactor path people that people currently on Blaze are looking for.

  Blaze > BlazeReact > JSX Templates > Pure JSX

How do we communicate that path? How do people on BlazeReact migrate their apps to JSX Templates?

1 Like

This is what I’ve been looking for. This really is a great solution. I was just asking around yesterday if it would be possible to move the HMTL out of JS code.

This ‘HTML in JS’ is what has been bugging me about React, and this will solve a huge problem (for me).

I don’t see any value in that. In my point of view this is only trying to create an illusion for people who don’t want to embrace writing rendering functions with the power of Javascript (vs. some custom template language like Spacebars). But in React rendering functions you need to use Javascript expressions a lot anyway. So I would encourage anyone who wants to write react components, to get a solid understanding of the Javascript basics.

Regarding separation of concerns I like and use the idea of creating stateless React components that just handle the concerns of rendering data and notifying the app code about user interactions. Those react components are easy to test and can be better reused in other contexts.

3 Likes

@sacha like the idea, I had a similar thought. I personally prefer less boilerplate. I don’t always see the value of splitting up containers/components into separate files, but I think this could be a good solution for Mantra.

If you really want to butcher React into something that’s low boilerplate, 99% free of javascript and has If/Else/Each just use the new functional/stateless style coupled with a package that provides , etc.

But… The way I see React, there’s no solutions with less boilerplate… Especially with pure components… Correct me if I’m wrong :smile:

Also, regarding the benefits of templates… I feel like it’s an inferior paradigm…

The benefits of templates @sacha mentions above can be solved easily compared to the benefits components have over templates.

Isn’t isolation of state (with containers and pure components) in React a gravitation towards the kind of separation of markup and logic you say templates favor over components?

1 Like

Why do people keep calling things containers when they’re actually the controller pattern? This is driving me nuts :frowning:

4 Likes

You try to use the language of the tool’s ecosystem, not what’s technically correct. Makes it easier to ask questions and discuss things.

2 Likes

Sorry man :smile: state container is probably better terminology…

1 Like

I feel like I must not be doing a great job of explaining my idea, as my proposal is specifically to use pure JSX, and not a templating language. I guess I shouldn’t have mentioned the word “templates” at all, but I wasn’t sure how else to describe it…

1 Like

I like the idea. Just JSX as we know it but no boilerplate. With ES6 around the corner you can also add import and export statements automatically.

You also ask:

How would we specify propTypes and defaultProps?

How do you do that with “normal” stateless components if it’s not a React.Component?

Also, regarding the benefits of templates… I feel like it’s an inferior paradigm…

ROTFL , so what makes the markup + code in react a component and what makes the markup + code in Blaze a template? (the tldr please)