KISSmetrics Style Guides

 › React/JSX Style Guide

Initial version derived from this blog post: https://reactjsnews.com/react-style-guide-patterns-i-like/

Method Organization

We lay out a component’s methods generally based on the order of its lifecycle methods:

React.createClass({
  propTypes: {},
  mixins: [],
  getInitialState: function() {},
  componentWillMount: function() {},
  componentWillUnmount: function() {},
  render: function() {}
});

We haven't generally used propTypes as I find they don't provide much value. They only issue warnings instead of errors in development mode, which makes it easy to ignore/miss any errors, and also provides no value when writing unit tests for a component. They are also not removed from production JS (without the user of another plugin/modifier), which means it will needlessly inflate the size of the production JS.

Custom functions should be placed below the React lifecycle methods, but above the render method. Preface these methods with an underscore to differentiate them from methods that are a part of React’s API, and to serve as a flag that it is a "private" method.

React.createClass({
  propTypes: {},
  mixins: [],
  getInitialState: function() {},
  componentWillMount: function() {},
  componentWillUnmount: function() {},
  _onChange: function() {},
  _onCreate: function() {},
  render: function() {}
});

It is much easier to always be able to scroll to the bottom of a file and expect to see the render method every time. As the render method grows, we break it up into smaller pieces, and have those sub-render methods placed above the "root" render method. This allows one to more easily find the primary render and then follow it down to the sub-render methods.

React.createClass({
  displayName: '',
  propTypes: {},
  mixins: [],
  getInitialState: function() {},
  componentWillMount: function() {},
  componentWillUnmount: function() {},
  _onChange: function() {},
  _onCreate: function() {},
  _renderHeader: function() {},
  _renderFooter: function() {},
  render: function() {}
});

Conditional HTML

It is worth repeating that, in JSX, anything in {} among HTML will be evaluated as JavaScript. So if you want to render something simple conditionally, you can use the same conditions or ternaries as you typically would in JavaScript:

{this.state.show && 'This is Shown'}
{this.state.on ? ‘On’ : ‘Off’}

For anything more complicated, using a sub-render method is likely the best course. Note that you can return undefined from a sub-render method, and React will simply render nothing. You cannot do this from the primary render method, though.

_renderSomething: function () {
  if (this.state.showDinosaurs) {
    return (
      <section>
        <DinosaurTable />
        <DinosaurPager />
      </section>
    );
  }
},

render: function () {
  return (
    <div>
      ...
      {this._renderSomething()}
      ...
    </div>
  );
}

JSX as a Variable or Return Value

JSX spanning multiple lines should be wrapped in parentheses like so:

var multilineJsx = (
  <header>
    <Logo />
    <Nav />
  </header>
);

JSX spanning a single line can disregard the parentheses,

var singleLineJsx = <h1>Simple JSX</h1>;

but anything complicated or with a likeliness of expanding could be wrapped in parentheses for readability/convenience.

Self-Closing Tags

Components without children should simply close themselves, as above with Logo,

<Logo />

as opposed to the unnecessarily more verbose

<Logo></Logo>

List Iterations

List iterations should be done inline, and unless the iteration is extremely simple, it should be offloaded to a sub-render method.

render: function() {
  return (
    <ul>
      {this.state.dinosaursList.map(function () {
        return <DinosaurItem item={dinosaur} />;
      })}
    </ul>
  );
}

Forms

Most of our form inputs should have reusable components built in to our Core component module. These components are built to be very dumb: props are passed in, and onChange callbacks are used to signal changes to the value. The owner of the input component is responsible for updating the state on their own component as needed.

Formatting Attributes

Instead of the long input element above, a cleaner and easier indentation would be:

<input
  type="text"
  value={this.state.newDinosaurName}
  onChange={this.inputHandler.bind(this, 'newDinosaurName')}
/>

as opposed to aligning attributes after the tag,

<input type="text"
       value={this.state.newDinosaurName}
       onChange={this.inputHandler.bind(this, 'newDinosaurName')} />

which is still more readable than no indentation, but takes a little more attention than it should.

Closing

These are a handful of patterns that we’ve found useful in writing React, and should by no means be considered authoritative at this point.