[1.3] react-jade module

Hi, I’m trying to use the react-jade npm package with meteor 1.3 beta.X.

It seems that some people can use react-jade with meteor 1.2 with an awful lot of hacks:

I’m installing the simple todos app and simply trying to “import” the react-jade module this way:

meteor create --example simple-todos-react
cd simple-todos-react/
meteor update --release 1.3-modules-beta.4
meteor update
npm install react-jade
mkdir client
echo "var jade = require('react-jade');" >> client/rj.js
meteor

Because in my browser console I get Cannot find module 'stream' and Cannot find module 'emitter' (not a good sign) I have to do the following:

npm install stream
npm install emitter

Then I’m stuck because of Uncaught TypeError: Emitter is not a function after the following code of index.js of the stream module is executed:

var Emitter = require('emitter');

function Stream() {
  Emitter.call(this);
}
Stream.prototype = new Emitter();

Am I doing something wrong? Any idea of a workaround? Should I open a new issue?
Thanks in advance for your help…

I opened issue 6035 for this.

Nope, didn’t get it to work, didn’t get time to look into building a custom loader package that meteor 1.2 would take and transform the jade-react into jsx.
So I’m still just using plain html like everyone else and hating it.

I have so many Jade templates to rewrite, I wont fully jump into React until react-jade is working. What a pity… :confused:

Two things I found relevant here:

  1. React forces you to write alot smaller components, so you end up with alot less html per component. I also put styling inline etc… so it means I’m no longer writing a template, rather, I’m writing a standalone html/css/js that is pluggable anywhere.
    For reading alot of html, Jade is good, but since my components have so little html, it becomes less relevant.

  2. For the writing part, I’ve found http://emmet.io/ to be useful. span -> TAB -> text rather than <span>text</span>

On reflection, writing react becomes alot more about thinking about your components than thinking about your page, your template and your code behind.

So to actually get to your observation, I think it’s a fallacy to think you’re rewriting your templates. You’re not. You’re actually creating little modules that are self-contained, you can pull it into your page and put it in the right places.

2 Likes

I had no problem keeping my code DRY with Blaze “components” in Jade (action buttons etc.). My code is already structured in a “component” way but still the Jade way of displaying HTML with tangled CSS classes really helps a lot with readability, thus helps avoiding bugs.
I totally understand the MDG choice of moving to React, but there are a lots of Jade users and I hope they will soon find to way to make the react-jade module work to avoid adding Jade frustration to Blaze frustration.

4 Likes

I think you’re right about the added Jade frustration. I’m trying to embrace the new React direction, but I really don’t want to have to go back to vanilla HTML… it feels like the dark ages.

3 Likes

Same here, my XHTML days are long gone. You could decide to use CoffeScript, that gives really nice React templates: see https://medium.com/@chetcorcos/shindig-react-js-coffeescript-c79d01197203#.n92cdftmp
(thanks to @ccorcos)

1 Like

I tried @ccorcos pure CoffeeScript solution a few weeks ago. It is very clever but IMHO it is not as convenient as the jade syntax. You have to write className everywhere and it has the same level of indentation as the tags it contains, I don’t have a good feeling about that…

Class and is annoying no so I’ve been using react-hyperscript lately. Plus it’s compatible with other vdom libraries

1 Like

No easy to setup Jade implementation is a stopper in React for me too.

And my Blaze templates are shorter than many React examples and open source apps I’ve seen, so the “React forces you to write a lot smaller components” argument is not my case.

2 Likes

I just found this old Sashko quote… :worried:

By the way I tried Vue instead of React but Jade templates are not working “out of the box” inside components : http://forum.vuejs.org/topic/2098/meteor-1-3-and-vue/8

Does anyone have any success with the ‘react-jade’ package in Meteor 1.3 final or does the Sashko quote mean there is currently no solution for using Jade with React on the client?

I haven’t tried, but this should work fine now in Meteor 1.3:

In proj root:

$ npm install --save react-jade

In your files:

import React from 'react';
import jade from 'react-jade';

var TodoList = React.createClass({
  render: jade`
ul
  each item in this.props.items
    li= item
`
});

along with the rest of the examples from https://github.com/pugjs/react-jade.

I tried but I get this error on the client when importing jade from ‘react-jade’:

modules.js:52242TypeError: fs.realpathSync is not a function. (In 'fs.realpathSync(path.join(path.dirname(__filename), file))', 'fs.realpathSync' is undefined)

My NPM package.json consists of: meteor-node-stubs, react, react-dom and react-jade.

@morganpattens I had the same error in issue 6035.

fs module is server only so on client it is replaced by an empty shell stub. What Sashko said seems to be the only solution.

By the way I switched to Meteor + webpack + Vue and now I can use jade and coffeescript and everything I want inside my Vue single file components instead of obeying facebook’s jsx syntactic diktat.

Weird… Jade (or Pug as it’s now called) and React are two of the most popular things in Node land: 10,000+ and 39,000+ stars on Github respectively. Still, few people seem to be interested in joining the two? :pensive:

I am a big fan of Jade… err Pug… wtf, but I stopped wishing for react-jade after a while because my render code fits on one page. I went scouring for my largest compoent and found this:

export const CharCreation = ({
  player,
  onCompleted,
  onCancelled,
  onChangeName,
  onChangeGender,
  onSetDifficulty,
  onChangeAttribute
  }) => (
  <div className="ui middle aligned center aligned grid">
    <div className="ui one column">
      <div className="ui stacked vertical segment">
        <div className="ui vertical segment">
          <div className="ui labeled fluid input">
            <div className="ui label">Character name:</div>
            <input
              type="text" name="name" placeholder="What word did your mother utter as you came kicking and screaming into this world?"
              onChange={(e) => onChangeName(e.target.value)}
              value={player.name}
            />
          </div>
        </div>
        <Attributes attributes={player.attributes} onChangeAttribute={onChangeAttribute}/>
        <div className="ui vertical segments">
          <div className="ui vertical segment">Character Gender</div>
          <div className="ui vertical segment">
            <Gender gender={player.gender} onChangeGender={onChangeGender}/>
          </div>
        </div>
        <GameDifficulty difficulty={player.difficulty} setDifficulty={onSetDifficulty}/>
        <div className="ui button primary" onClick={() => onCompleted(player)}>Ok</div>
        <div className="ui button" onClick={onCancelled}>Cancel</div>
        <div className="ui button">View Icon</div>
        <div className="ui button">Help</div>
      </div>
    </div>
  </div>
);

That’s my biggest component and it’s 37 lines. Whilst I agree that Jade… f**k, Pug, would make it much prettier to the eye, cognitively, it almost makes no difference.

When I was doing blaze pages, the typical html -> jade transformation would be something like 400 lines to 200 lines and that takes alot of the cognitive load off traversing the nested elements, but with react, it’s not a big difference.

Here’s the Attributes component (27 lines):

const Attributes = ({attributes, onChangeAttribute}) => (
  <div>
    {
      _.map(attributes, function (attribute, i) {
        let attrName = attribute.name;
        return (
          <div className="ui segments" key={i}>
            <div className="ui segment left aligned">
              <h4 className="ui header">{attrName}:</h4>
              <div className="ui indicating progress" data-percent={attribute.value}>
                <div className={`bar test-${attrName}-bar`} style={{width:attribute.value+'%', minWidth:0}}></div>
                <div className={`label test-${attrName}-description`}>{getAttributeDescription(attrName, attribute.value)}</div>
              </div>
              {attrName !== "Available" ?
                buttons(onChangeAttribute, attrName) : ''}
            </div>
          </div>
        )
      })
    }
  </div>
);

Game difficulty (19 lines):

const GameDifficulty = ({
  difficulty,
  setDifficulty
}) => {
  return (
    <div className="four ui buttons">
      {difficultyLevels.map(function (level, i) {
        return (
          <div
            className={classNames('ui icon button', {active:difficulty === level.level}) }
            onClick={() => setDifficulty(level.level)}
            key={i}>
            <div><i className={level.icon} /></div>
            <label>{DifficultyLevel[level.level]}</label>
          </div>
        );
      }, this)}
    </div>
  )
};

Gender (19 lines):

const Gender = ({
  gender,
  onChangeGender
  }) => (
  <div className="equal width column">
    <div className="ui large buttons">
      <div className={classNames("ui labeled icon button", {active:gender === 'male'})}
           onClick={() => {onChangeGender('male');}}>
        <i className="large male icon"/>
        Male
      </div>
      <div className="or"></div>
      <div className={classNames("ui labeled icon button", {active:gender === 'female'})}
           onClick={() => {onChangeGender('female')}}>
        <i className="large female icon"/>
        Female
      </div>
    </div>
  </div>
);

All together it renders this page:
http://cotwmtor.meteorapp.com/new

Not the prettiest but a fair amount of interactions for 65 lines of render code that I can look at/debug separately.

So I think people haven’t been focused on this because Jade solves a problem of templates and React doesn’t have templates.

IMHO jsx files syntax is the worst thing that happened to computer science since PHP.

Because I had to refactor my code for Meteor 1.3 anyway, I decided to switch from React to the amazing Vue (+webpack). Now I can use ultra-readable single file components with all the pre-processors I want, with hot reloads and all.

Good luck debugging/maintaining jsx spaghetti code all, jade/pug or not.