Getting Facebook's react.js library JSX syntax to play nicely with jslint?

23,237

Solution 1

(Update: This post is from 2013 and obsolete now.)

I use JSHint + JSX.

It shouldn't require a fork of JSHint, there should be a way to tell JSHint to disable all warnings for a block of code. Unfortunately there is no such way to disable all warnings, only a specific set of warnings, so I may end up submitting a pull request to add this, or change linters.

Update: We submitted a pull request which was accepted. To disable all warnings, add /*jshint ignore: start */ to start the section, and /*jshint ignore: end */ to end it.

As you noted, the workflow Facebook and Instagram use is to lint outside the IDE from the command line.

Your other option is to extract all your JSX templates into their own files, and make them a function of scope instead of existing inside an implicit lexical scope. We tried it out and didn't like the amount of boilerplate.

(Note: I am not affiliated with the React team.)

Solution 2

I tried to follow Dustin's and STRML's advice on this thread, and here's what worked best for me.

Development Setup

I use Sublime Text with SublimeLinter + SublimeLinter-jshint + SublimeLinter-jsxhint.
These are very nice plugins that let me see mistakes when I save the file, both for JS and JSX files:

These plugins respect your project's .jshintrc and I can't recommend them enough.

Make sure to follow installation instructions for all three packages, or they won't work:

You can configure the linter to execute every few seconds, on file save, or manually.

Build Step, Commit Hook, etc

We're using JSHint as part of our Git workflow and as a build step to enforce the guidelines. We could have used jsxhint but we wanted to keep using grunt-contrib-jshint so this wasn't an option.

Right now, we're running normal jshint as a build step after react transformation, so it just processes the output JS files.

It would be cool if somebody forked grunt-contrib-jshint and made a version that works with jsxhint, but it doesn't look like an easy task to me. (Update: somebody did just that but I haven't tested it.)

Ignoring Violations in Generated Code

JSX compiler generates code that breaks a few our conventions.

I didn't want to use ignore:start and ignore:end as suggested by Dustin since this would effectively disable all linting inside render methods. It is a bad idea in my book. For example, excluding render method from linting makes linter think I don't use some of the libraries and child components that I declare with require at the top of the file. Therefore, the need to ignore things spreads from render method to the rest of the file, and this defeats the purpose of ignore:start completely.

Instead, I explicitly decorate each render method with three JSHint options that JSX compiler (currently) breaks for me:

render: function () {
  /* jshint trailing:false, quotmark:false, newcap:false */
}

This is sufficient in my case; for your .jshintrc this may need some tuning.

Solution 3

JsxHint and JSHint arent the best tools for linting JSX. JSHint does not support JSX and all JsxHint does is transforms JSX and then runs JSHint on the transformed code. I have been using (and would highly recommend) ESLint with the React plugin. This is better since Eslint can parse any Javascript flavor using custom parsers like esprima-fb or babel-eslint (see update below).

Sample .eslintrc file:

{
    "parser": "esprima-fb",
    "env": {
        "browser": true,
        "node": true
    },

    "rules": {
        "no-mixed-requires": [0, false],
        "quotes": [2, "single"],
        "strict": [1, "never"],
        "semi": [2, "always"],
        "curly": 1,
        "no-bitwise": 1,
        "max-len": [1, 110, 4],
        "vars-on-top": 0,
        "guard-for-in": 1,
        "react/display-name": 1,
        "react/jsx-quotes": [2, "double", "avoid-escape"],
        "react/jsx-no-undef": 2,
        "react/jsx-sort-props": 0,
        "react/jsx-uses-react": 1,
        "react/jsx-uses-vars": 1,
        "react/no-did-mount-set-state": 2,
        "react/no-did-update-set-state": 2,
        "react/no-multi-comp": 0,
        "react/no-unknown-property": 1,
        "react/prop-types": 2,
        "react/react-in-jsx-scope": 1,
        "react/self-closing-comp": 1,
        "react/wrap-multilines": 2
    },

    "ecmaFeatures": {
        "jsx": true
    },

    "plugins": [ "react" ],

    "globals": {
        "d3": true,
        "require": "true",
        "module": "true",
        "$": "true",
        "d3": "true"
    }
}

UPDATE

esprima-fb will soon be deprecated by Facebook. Use babel-eslint as a parser for eslint. A good place to know more about how you can setup Babel & Eslint to work with React is this Github project.

Solution 4

See JSXHint, a wrapper around JSHint I wrote that lints the output from react-tools. This is a step up from ignoring a block of lines as it will actually lint the generated javascript.

It can be used with Sublime Text via SublimeLinter with this plugin.

Solution 5

Guys maintaining the repo are incredibly helpful. You just have to run it threw the JSX transform to produce valid javascript unless someone creates a fork of jshint. If there is enough interest, it might be put on the roadmap for future release of the react framework. Can look at the coversation thread here.

Share:
23,237
TYRONEMICHAEL
Author by

TYRONEMICHAEL

Senior Software Engineer

Updated on November 15, 2020

Comments

  • TYRONEMICHAEL
    TYRONEMICHAEL over 3 years

    I am playing around with the Facebook's react.js library. I am trying to use their JSX syntax which describes creating a view in the following way.

    /** @jsx React.DOM */
    var HelloMessage = React.createClass({
      render: function() {
        return <div>{'Hello ' + this.props.name}</div>;
      }
    });
    
    React.renderComponent(<HelloMessage name="John" />, mountNode);
    

    JSLint obviously does not like this ("expected an identifier and instead saw ' <';" - JavaScript syntax error), so how do I get around this in my .jshintrc file?

  • Daniel Miladinov
    Daniel Miladinov over 10 years
    I recently put in a pull request to jshint that adds a feature to ignore a block of lines in javascript and resume linting afterward. I specifically had JSX in mind.
  • tkone
    tkone over 10 years
    Been working on this specifically. The recommendation from the IRC channel is to lint the output from the jsx "transpiler". I've actually been working on a node module that wraps jshint that will transform any jsx files it find.
  • Dan Abramov
    Dan Abramov about 10 years
    The pull request is merged, by the way, at least as of JSHint 2.4. However, I highly recommend using granular options instead of ignore:start: see rationale.
  • Nils Magne Lunde
    Nils Magne Lunde over 9 years
    I followed your instructions, but I am having trouble getting Sublime to use the correct linter for the .jsx-files. It is always using jshint instead of jsxhint. How did you get around this problem?
  • Dan Abramov
    Dan Abramov over 9 years
    @NilsMagneLunde Does it show JSX syntax is being used in lower right corner? Did you restart Sublime?
  • Nils Magne Lunde
    Nils Magne Lunde over 9 years
    No, it doesn't. Changing it to jsx seems to have solved the problems :-) Now I just need to figure out how to make Sublime recognize the jsx-files automatically. Thanks!
  • Dan Abramov
    Dan Abramov over 9 years
    @NilsMagneLunde Maybe you need to “Open all with current extension as”? See i.imgur.com/3thgqp6.png
  • vasa
    vasa about 9 years
  • Cezary Daniel Nowak
    Cezary Daniel Nowak almost 9 years
    There is also online version: www.jsxhint.com
  • STRML
    STRML almost 9 years
    As the author of JSXHint... I wholeheartedly agree. JSXHint is a hack I put together in a weekend so I could just get some basic linting working without terrible ignore hacks. ESLint actually parses the code correctly and has support for a lot more ES6/ES7 features to boot. It's a better project and I have switched to it in my own work as well.
  • Yan Foto
    Yan Foto almost 9 years
    I was hoping for a more generic answer. This one assumes that sublime is the used IDE. :(