This was originally published Jan 5, 2016.

Sublime Text Setup for React.JS Development: Linting, Emment, and Formatting

In this tutorial, I will go over setting up Sublime Text 3 for linting, Emmet, formatting, and other ways to keep React.js development easy. I started to write this post when I realized just how quickly React.js tutorials become out of date with respect to Sublime Text plugins (as recent as only 9 months ago!). I took a good deal of time to setup my Sublime environment to one I was moderately happy with.

Sidenote: I may be somewhat obsessed with optimizing my Sublime, but taking the time to setup your environment can go a long way in time savings. If you already use Emmet, snippets, linting, and formatting to the full -- I'm preaching to the converted. If you don't -- please, **please* check those out first! If you need to be convinced, XKCD (below) should tell you why:*



Dan Abramov's Lint Like It's 2015 is the resource on installing ESLint, along with syntax highlighting and all that good stuff. One thing to note is that ESLint has been updated for easier installation. As per their insructions:

Install ESLint:

  npm install -g eslint

And setup with ESLint is far, far easier:

  eslint --init

Where they will ask you if you want to setup a customized .eslintrc or use a popular style guide. I chose to create my own. The resulting .eslintrc:

  "extends": "eslint:recommended",
  "plugins": ["react"],
  "ecmaFeatures": {
    "modules": true,
    "jsx": true
  "rules": {
    "no-alert": 2,
    "no-array-constructor": 2,
    "no-caller": 2,
    "no-catch-shadow": 2,
    "no-empty-label": 2,
    "no-eval": 2,
    "no-extend-native": 2,
    "no-extra-bind": 2,
    "no-implied-eval": 2,
    "no-iterator": 2,
    "no-label-var": 2,
    "no-labels": 2,
    "no-lone-blocks": 2,
    "no-loop-func": 2,
    "no-multi-spaces": 2,
    "no-multi-str": 2,
    "no-native-reassign": 2,
    "no-new": 2,
    "no-new-func": 2,
    "no-new-object": 2,
    "no-new-wrappers": 2,
    "no-octal-escape": 2,
    "no-process-exit": 2,
    "no-proto": 2,
    "no-return-assign": 2,
    "no-script-url": 2,
    "no-sequences": 2,
    "no-shadow": 2,
    "no-shadow-restricted-names": 2,
    "no-spaced-func": 2,
    "no-trailing-spaces": 2,
    "no-undef-init": 2,
    "no-underscore-dangle": 2,
    "no-unused-expressions": 2,
    "no-use-before-define": 2,
    "no-with": 2,
    "camelcase": 2,
    "comma-spacing": 2,
    "consistent-return": 2,
    "curly": [2, "all"],
    "dot-notation": [2, {
      "allowKeywords": true
    "eol-last": 2,
    "no-extra-parens": [2, "functions"],
    "eqeqeq": 2,
    "key-spacing": [2, {
      "beforeColon": false,
      "afterColon": true
    "new-cap": 2,
    "new-parens": 2,
    "quotes": [2, "double"],
    "semi": 2,
    "semi-spacing": [2, {
      "before": false,
      "after": true
    "space-infix-ops": 2,
    "space-return-throw-case": 2,
    "space-unary-ops": [2, {
      "words": true,
      "nonwords": false
    "strict": [2, "global"],
    "yoda": [2, "never"]


and the resulting .esformatter:

  "preset": "default",

  "plugins": [

  "quotes": {
    "type": "double"

  "collapseObjects": {
    "ObjectExpression": {
      "maxLineLength": 79,
      "maxKeys": 1

  "indent": {
    "value": "  ",
    "AlignComments": false

  "whiteSpace": {
    "before": {
      "ObjectExpressionClosingBrace": 0,
      "ModuleSpecifierClosingBrace": 0,
      "PropertyName": 1
    "after": {
      "ObjectExpressionOpeningBrace": 0,
      "ModuleSpecifierOpeningBrace": 0

Installing the rest of SublimeLinter-contrib-eslint should be the same as Dan Abramov's tutorial. The only thing I would suggest is to not uninstall SublimeLinter-jshint just yet - instead, I use SublimeLinter's "toggle linter" function. The reason is that my JSHint has been customized and tweaked, and I want to save those changes.

For a linting shortcut, you can click Command + E to skip to each error. Just add the following to your Default (OSX).sublime-keymap:

  "keys": ["super+e"],
  "command": "sublimelinter_goto_error",
  "args": {
    "direction": "next"

Emmet integration and auto-expansion by tab

When I first started writing JSX I realized just how much I missed HTML autocomplete, and disliked having to rename class to className. Luckily, an easy solution exists!

Copy and paste this into your Default (OSX).sublime-keymap:

    "keys": ["tab"],
    "command": "chain",
    "args": {
        "commands": [
            ["reg_replace", {
                "replacements": ["js_class"]
    "context": [{
        "operand": "source.js",
        "operator": "equal",
        "match_all": true,
        "key": "selector"
    }, {
        "key": "preceding_text",
        "operator": "regex_contains",
        "operand": "(\\w+>\\w+|\\s(\\.?|a|div|span|p|button)\\.\\w+)",
        "match_all": true
    }, {
        "key": "selection_empty",
        "operator": "equal",
        "operand": true,
        "match_all": true


And add the following to reg_replace.sublime-settings:

  "replacements": {
    "js_class": {
      "find": " class=\"",
      "replace": " className=\"",
      "greedy": true,
      "case": false

And now Emmet expansions should work!


As I love optimizing my Sublime environment, I took far too long to get a working version of JSFormat for JSX. I love JSFormat and was devastated when I saw that support for JSX was rejected.

Other suggestions I have seen is to use the HTML-CSS-JS Prettify plugin and in the JS section, add jsx to the allowed_file_extension, and then change ex4 to true. However, this is really a plugin that helps you ignore XML syntax in JS files, and I wasn't happy with the spacing or how glaring formatting errors (i.e. newlines where they shouldn't be) weren't corrected.

My current setup uses Sublime JSFMT, which I think is the best so far. You can include a variety of esformatter plugins (a godsend!) and it allows for far greater customization.

In jsfmt.sublime-settings-User, I have this:

  // autoformat on save
  "autoformat": false,

  // array of extensions for autoformat
  "extensions": ["js",

  // options for jsfmt
  "options": {
    "preset": "jquery",
    "indent": {
      "value": "  "
    // plugins included
    "plugins": [
      // "esformatter-jsx-ignore",
      // "esformatter-braces",
      // "esformatter-dot-notation",
      // "esformatter-collapse-objects"
    "jsx": {
      "formatJSX": true,
      // change these to your preferred values
      // refer to for more options
      "attrsOnSameLineAsTag": true, // move each attribute to its own line
      "maxAttrsOnTag": 1, // if lower or equal than 3 attributes, they will be kept on a single line
      "firstAttributeOnSameLine": true, // keep the first attribute in the same line as the tag
      "alignWithFirstAttribute": true, // do not align attributes with the first tag
      "spaceInJSXExpressionContainers": " ", // default to one space. Make it empty if you don't like spaces between JSXExpressionContainers
      "htmlOptions": {
        // put here the options for js-beautify.html
  "options-JSON": {
    "plugins": [
    "quotes": {
      "type": "double"
  "node-path": "node",
  "alert-errors": true,
  "ignore-selection": false


And there you have it! I haven't gone into detail about snippets, Webpack, Grunt plugins and other details, but this should be enough to get you started for more convenient React.js development!