React Style Guide

The idea of "idiomatic" React hasn’t been explicitly written on, so I thought I’d offer some conventions that my team at Tune has been using during the past few months of adoption. For the sake of this article, scope will be limited to coding style in React components - not styling, componentization, or Flux strategies. Also, this is meant to be a living document - and I am sure there are better ideas out there - so any comments and feedback are more than welcome.

Method Organization

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

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

Setting a displayName will help with debuggable warnings when developing - I like putting that at the very top, followed by propTypes and mixins. PropTypes are particularly useful for explicitly documenting your expectations for how the component is to be used, in addition to adding validation on incoming props.

If you have custom functions, I prefer to preface these with an underscore to differentiate them from methods that are a part of React's API. I typically place them immediately above the render function.

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

I originally thought custom functions should be placed underneath the render method, but pragmatically, it is much easier to always be able to scroll to the bottom of a file and expect to see the render every time.

As much as I can, I also prefer for all of the component's JSX to be located in that render method.

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, I have typically been creating a variable inside the render method, suffixed with 'Html':

var dinosaurHtml = '';  
if (this.state.showDinosaurs) {  
  dinosaurHtml = (
    <section>
      <DinosaurTable />
      <DinosaurPager />
    </section>
  );
}

return (  
  <div>
    ...
    {dinosaurHtml}
    ...
  </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

I used to do my list iterations like above in dinosaurHtml. I've realized that list iterations are better done inline, especially if each list item will be rendered as a component. You may even be able to reduce to one line with fat arrows:

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

This does require the harmony flag on JSX to be included, which will toggle certain ES6 features (fat arrows, template strings, destructuring, and rest parameters), listed here: http://kangax.github.io/compat-table/es6/#jsx. If you're incurring the cost of JSX compilation, you might as well also incur the cost of ES6 transpilation as well, using either the JSX harmony flag or a separate ES6 transpiler (we use 6to5).

Forms

[This is pushing the boundary of this article's scope, but may generally be a helpful pattern.]

I used to think that you should track your form input values somewhere at all times, either in the component state or a Flux store. This would mean using ReactLink from React Addons (for storing in the component state) or writing your own handlers (for storing in a Flux store). If you went with a handler to store in Flux, you could write one abstractly and then curry it for each field, like so:

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

where inputHandler looks something like:

function(fieldName, event) {  
  actions.propagateValue({
    field : fieldName,
    value : event.target.value
  });
}

It seems a little heretical to say, but I'm starting to think that it is easier not to track changes/state for forms anywhere if it can be avoided, and to basically extract all of the values out of the form manually via the DOM whenever they are needed (for example, only when the Create button is clicked).

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. If you have contradicting ideas, please offer them in the comments as this sort of discussion is beneficial for the React ecosystem as a whole.

I would love to see other style guides emerge to address styling, componentization (including when to use mixins, considerations between props and state, and communication strategies), and Flux.

Thanks for reading!

View Comments