An opinionated guide to React.js – Best practices and conventions

I’ve been using React.js for a little while now, both in my 9 to 5 job and for my own projects, and during that time I have started evolving my own set of React.js best practices.

The following guidelines mostly focus on component structure and JSX. However, they are not hard and fast rules, but more of an opinionated set of guidelines I choose to adhere to that make my code more readable, more robust and easily maintainable.

Note: This article does not provide explanations of the React paradigms or idioms mentioned here or used in the examples, that is best left to the excellent documentation provided by the React team.

Component organisation

As with any code, it’s important to have consistency. This of course also applies when structuring your React components. I use the following pattern:


    React.createClass({

        propTypes: {},
        mixins : [],

        getInitialState: function() {},
        getDefaultProps: function() {},

        componentWillMount : function() {},
        componentWillReceiveProps: function() {},
        componentWillUnmount : function() {},

        _parseData : function() {},
        _onSelect : function() {},

        render : function() {}

    })

I like to declare propTypes at the top of my component as they are a useful guide to a components expected usage (see section below for more on this), followed by the mixins because it is handy to initially know exactly what external behaviours the component is using/dependent on.

I choose to split the life-cycle methods into those that occur before an instance of the component is created (e.g. getInitialState, getDefaultProps) and those which occur during the mounting/updating/mounted cycle (e.g. componentWillMount, shouldComponentUpdate). Furthermore, I find that declaring the lifecycle methods in order of execution also makes the component easier to reason about.

I always have my custom methods follow the lifecycle methods and be prefixed with an underscore to make them easier to identify. I’ll usually also group these by utility (parsers, event handlers, etc).

I like the render method to always be last. The render method is a mandatory lifecycle method and it’s almost always the function I need to find first when I open a file. Consequently, it’s pragmatic to have it in a consistent location across all of my components.

In general, my mixins will follow the same conventions as regular components.

Always set propTypes for validation and self-documentation

I always use propTypes to provide validation for each prop the component will receive. Furthermore, this also provides a self-documenting reference for how the component should be used, and what props it needs to be passed.


    propTypes: {
        arrayProp: React.PropTypes.array,
        boolProp: React.PropTypes.bool,
        funcProp: React.PropTypes.func,
        numProp: React.PropTypes.number,
        objProp: React.PropTypes.object,
        stringProp: React.PropTypes.string,
    }

JSX

Let’s face it, JSX can look pretty ugly at times and is one of the more common reasons developers are put off by React. However, by following a few general guidelines for handling JSX in components, it’s far more readable and not such an eyesore.

Multi-line JSX

No matter how few elements are being returned, I choose to write any JSX which contains nested elements across multiple lines with indentation to enhance readability, i.e:


    return (
        <div>
            <ComponentOne />
            <ComponentTwo />
        </div>
    );

Rather than…


    return (<div><ComponentOne /><ComponentTwo /></div>);

Furthermore, while the parenthesis are not technically required with a single line JSX statement, I still use them for the sake of consistency (and because unrestrained elements floating about in my JS makes my left eye twitch uncontrollably).

Conditional JSX

When I have conditional elements that needs to be returned depending on state, props, or another condition, I declare an empty variable at the top of the render function and only populate it with JSX if the condition is met. When the variable is returned in the render method return statement, it’ll either render the conditional elements, or nothing at all.


    var optionalElement;

    if (this.props.condition) {
        optionalElement = (<div> … </div>);
    }

    return (
        <div>
            …
            {optionalElement}
            …
        </div>
    );

In-line list iteration

Where possible, I like to iterate over lists of data in-line in the returned JSX unless its internal logic is sufficiently complex enough to warrant moving outside of the return statement and populating an array for rendering.


    return (
        <div>
            {this.props.list.map(function(data, i) {
                return (<Component data={data} key={i} />)
            })}
        </div>
    );

Indentation and new line for component attributes

When there are enough attributes on a component that displaying them inline becomes untidy (usually 3 or more), I always display them on multiple lines and indent each one. i.e.


    <Component
        attribute={...}
        anotherAttribute={...}
        attributeThree={...}
        …
    />

Rather than…


    <Component attribute={...} anotherAttribute={...} attributeThree={...} />

Conclusion

These guidelines are by no means authoritative or exhaustive, but I feel they are a good starting point for organising and standardising React components and some of the more common use cases I encounter.

Hopefully these guidelines provide a useful starting point for organising your React components. Be sure to leave a comment if you have a question!

52 thoughts on “An opinionated guide to React.js – Best practices and conventions”

  1. Wow! Rarely do I read a style guide and agree with every single point. This is exactly the same as our guide for our huge React codebase in Atlas at Facebook. Here are a few more we have found helpful:

    – PropType declarations should be grouped into required then non-required separated by a new line, and each group alphabetically sorted. Props passed to a component should be alphabetically sorted without regard to required status.
    – Always use a component level function as an event handler. Instead of onClick={SomeActionCreator.someAction}, do onClick={this._someButtonClicked}, and call SomeActionCreator.someAction inside. This mostly came out of a bug where an optional parameter was added to an action creator call, and it was then being passed the Event object.
    – I personally prefer inline ternaries for conditional rendering, but we also use the style you suggested often.

    • Hey David – seeing as using the ES6 classes don’t add any great benefit over using the standard React.createClass and usage comes with some constraints/downsides (Unable to use Mixins, imperative property assignment for propTypes, defaultProps, etc), I personally don’t have any plans to start using the ES6 classes any time soon.

      However, the bulk of my guidelines (component structure, JSX related rules) would still apply to the ES6 classes.

    • Nice sharing John thanks !

      About the conditional JSX, what do you think about the following :

      if(this.props.expired){
      return (…);
      }else{
      return (..);

    • Stéphane,

      I would assign the result of the evaluation block to a variable and return that. I prefer to only have one exit point out of a function if I can help it. It makes it easier to reason about if you don’t have to look for multiple exit locations.

    • @John Cobb – well, there’s the advantage that the ES6 version isn’t a deprecated version that the creator has said will be phased out completely in the future…

    • @Bryan You’ll notice that the article, and comment you’re replying to, were written over 18 months ago. While you are correct now and I wholeheartedly agree, at the time of writing the article ES6 React classes were not available at all, and if you take the time to look at the link in the comment above – they had just been introduced in a pre-release beta. However, I appreciate you taking the time to comment, albeit anonymously and with unnecessary condescension notwithstanding.

  2. Thanks, this is a nice post. Something I’ve been curious about, maybe something you’d be willing to write about sometime: how do you organize component files themselves? Do they get organized by page, or by purpose? It’s still somewhat of an open question to me since a lot of my components are not bound to a single specific page.

  3. What’s the best way to comment inside a react js file? this has led to issues as // comments cause errors.

    I was working on some components named for example Profile.js and commented with “//” so I could reference some logic I used later when I go back and look at it. Thanks!

  4. I’m just a beginner with react.js , I was searching for a way to document my component.
    This page helped me a lot 🙂
    Thanks you

  5. It’s worth pointing out that key={i} “silences React” but does so by entirely ignoring what the key is for. An array can be reordered, so the key property is for making sure that even if moved to a different spot, React knows it’s the same element, something that key={i} explicitly negates. You want to pass some “unique” value in as key, extracted from the data you’re using in your map

  6. I have created some react components, which opens on click of div and on close I get hold of the node, and unmountComponentAtNode and remove it. Though it seems it doesn’t really remove the component. Because in the Chrome Debug React Console, it shows the two components with the same values. Is it expected behavior that it doesn’t update in the chrome?

    thanks.

  7. Hey John,

    Excellent article. One thing I have found very useful to enforce is comments with details about propTypes. For example:

    propTypes: {
    someStuff: React.PropTypes.array // object literals with user id and name
    }

  8. Just started using react a few days ago. Still not sure about the best patterns and practices within react. Is it common to pass say functions for executing after an update in a react component to update something else in external ( non component code ).

    Like if my react component had an event property with events: { update: null, remove: null }

    so that after I instantiate my component the user can define.

    var myComp = React.Render(, placeToMount);

    myComp.events.update = function() {
    console.log(“updated”);
    }

    obviously there would be a check if the event.update function was null in whatever code would handle the update.

    I’m guessing it’s not a standard as you would probably just include that as another component within your component.

  9. Great advice. One question: do you use browserify/reactify? How do you split up components between files? How do you associate them with their requisite stores (when the stores are in different files?)

  10. Agree with everything.

    But in Conditional JSX I like to have the condition and the jsx directly in the return statement. I think it makes it easier to see what markup will be rendered.

    return (

    {this.props.conditional && (

    )}

    );

Comments are closed.