eslint-config-crowdanalyzer-react
v3.0.0
Published
Crowd Analyzer eslint react configuration
Downloads
21
Readme
CrowdAnalyzer React/JSX Style Guide
Table of Contents
Basic Rules
1.1 Only include one React component per file. (no-multi-comp)
// bad
var Hello = createReactClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
var HelloJohn = createReactClass({
render: function () {
return <Hello name = "John" /> ;
}
});
// good
var Hello = require('./components/Hello');
var HelloJohn = createReactClass({
render: function() {
return <Hello name="John" />;
}
});
1.2 Always use JSX syntax.
1.3 Do not use React.createElement
unless you’re initializing the app from a file that is not JSX.
1.4 Always use a displayName for components when exporting them so they can be easily identified in react dev tools. this can be easily done by the transpiler as long you export the component correctly. see examples below
// bad
export default () => {
return <button />;
}
// good
// Named export (declaration)
export function Button() {
return <button />;
}
// Named export (arrow)
export const Button = () => {
return <button />;
}
// Default export (declaration)
export default function Button() {
return <button />;
}
// Default export (arrow)
const Button = () => {
return <button />;
}
export default Button;
Classes vs Stateless
2.1 If you have internal state and/or refs, prefer class extends React.Component over React.createClass. if you don't have state or refs, prefer normal functions (not arrow functions) over classes (prefer-es6-class) & (prefer-stateless-function)
// bad
const Listing = React.createClass({
render() {
return <div>{this.state.hello}</div>;
}
});
const Listing = ({ hello }) => (
<div>{hello}</div>
);
// good
class Listing extends React.Component {
render() {
return <div>{this.state.hello}</div>;
}
}
function Listing({ hello }) {
return <div>{hello}</div>;
}
Naming
3.1 Extensions: Use .jsx
extension for React components. If you use TypeScript, you will use .tsx
extension by default. (jsx-filename-extension)
// bad
// filename: MyComponent.js
function MyComponent() {
return <div />;
}
// good
// filename: MyComponent.jsx
function MyComponent() {
return <div />;
}
// filename: MyComponent.tsx
const MyComponent: React.FC = () {
return <div />;
}
3.2 Filename: Use PascalCase for filenames. E.g., ReservationCard.jsx
. (jsx-pascal-case)
3.3 Reference Naming: Use PascalCase for React components and camelCase for their instances. (jsx-pascal-case)
// bad
import reservationCard from './ReservationCard';
const ReservationItem = <ReservationCard />;
// good
import ReservationCard from './ReservationCard';
const reservationItem = <ReservationCard />;
3.4 Component Naming: Use the filename as the component name. For example, ReservationCard.jsx
should have a reference name of ReservationCard
. However, for root components of a directory, use index.jsx
as the filename and use the directory name as the component name:
// bad
import Footer from './Footer/Footer';
import Footer from './Footer/index';
// good
import Footer from './Footer';
Alignment
4.1 Avoid extra closing tags for components without children (self-closing-comp)
// bad
var HelloJohn = <Hello name="John"></Hello>;
// good
var contentContainer = <div className="content"></div>;
var intentionalSpace = <div>{' '}</div>;
var HelloJohn = <Hello name="John" />;
var Profile = <Hello name="John"><img src="picture.png" /></Hello>;
var HelloSpace = <Hello>{' '}</Hello>;
4.2 Enforce the closing bracket location for JSX multiline elements, the closing bracket should be placed after props (closing-bracket-location)
// bad
var x = function() {
return <Say
firstName="John"
lastName="Smith"
>
Hello
</Say>;
};
// good
<Hello
firstName="John"
lastName="Smith" />;
<Say
firstName="John"
lastName="Smith">
Hello
</Say>;
4.3 The closing tag location should be on the same line if it is one line expression, while it should be aligned with the opening tag if it is multiline expression. (jsx-closing-tag-location)
// bad
<Hello>
marklar
</Hello>
<Hello>
marklar</Hello>
// good
<Hello>
marklar
</Hello>
<Hello>marklar</Hello>
4.4 Ensure correct position of the first property. (jsx-first-prop-new-line)
// bad
<Hello foo={{
}}
bar />
// good
<Hello foo={{}} />
<Hello
foo={{}}
bar
/>
4.5 Limit the maximum of props on a single line can improve readability, If it is multiline expression, then it’s one property per line (jsx-max-props-per-line)
// bad
<Hello
firstName="John" lastName="Smith" />
// good
<Hello firstName="John" lastName="Smith" />
<Hello
firstName="John"
lastName="Smith"
/>
4.6 Limit every line in JSX to one expression each. (jsx-one-expression-per-line)
// bad
<App><Hello /><Hello2 /></App>
// good
<App>Hello</App>
<App>{"Hello"}</App>
<App>
<Hello />
<Hello2 />
</App>
4.7 Avoid unnecessary curly braces in JSX props and / or children. (jsx-curly-brace-presence)
// bad
<App>{'Hello world'}</App>;
<App prop={'Hello world'} attr={"foo"} />;
// good
<App>Hello world</App>;
<App prop="Hello world" attr="foo" />;
Spacing
5.1 Avoid using extra spaces, React removes extraneous new lines between elements when possible, it is possible to end up with inline elements that are not rendered with spaces between them and adjacent text. This is often indicative of an error, so this rule attempts to detect.(jsx-child-element-spacing)
// bad
<div>
Here is a
<a>link</a>
</div>
<div>
<b>This text</b>
is bold
</div>
// good
<div>
Spacing is
{' '}
<a>explicit</a>
</div>
<div>
Lack of spacing is{/*
*/}<a>explicit</a>
</div>
5.2 Avoid spaces inside of curly braces in JSX attributes and expressions or around equal signs in JSX attributes (jsx-curly-spacing) & (jsx-equals-spacing)
// bad
<Hello name={ firstname } />;
<Hello name={ firstname} />;
<Hello name={firstname } />;
<Hello name={
firstname
} />;
<Hello name = {firstname} />;
<Hello name ={firstname} />;
<Hello name= {firstname} />;
// good
<Hello name={firstname} />;
<Hello name={{ firstname: 'John', lastname: 'Doe' }} />;
<Hello>{firstname}</Hello>;
<Hello>{ firstname }</Hello>;
<Hello>{
firstname
}</Hello>;
<Hello name />;
<Hello {...props} />;
5.3 Enforce consistent indentation style. 2 spaces
.(jsx-indent) & (jsx-indent-props) & (indent)
// bad
<App>
<Hello />
</App>
// bad
<App>
<Hello />
</App>
// bad
{
hello: "world"
}
// good
<App>
<Hello />
</App>
// good
{
hello: "world"
}
5.4 Avoid multiple spaces between inline JSX props. (jsx-props-no-multi-spaces)
// bad
<App spacy />
<App too spacy />
// good
<App cozy={true} />
<App very={true} cozy={true}/>
5.5 Avoid spaces after the opening bracket, before the closing bracket and between the angle bracket and slash of JSX self-closing elements. Leave space before the closing bracket of self-closing elements. (jsx-tag-spacing)
// bad
<Hello firstname="John"/>
<Provider>< /Provider>
< Hello firstName="John"/>
// good
<Hello firstName="John" />
<Provider></Provider>
Props
6.1 Prevent missing props validation in a React component definition. (prop-types)
// bad
var Hello = createReactClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
// good
var Hello = createReactClass({
propTypes: {
name: PropTypes.string.isRequired,
},
render: function() {
return <div>Hello {this.props.name}</div>;
},
});
6.2 Enforce consistent usage of destructuring assignment of props, state, and context. (destructuring-assignment)
// bad
const MyComponent = (props) => {
return (<div id={props.id} />)
};
// good
const MyComponent = ({id}) => {
return (<div id={id} />)
};
6.3 Prevents passing of props that add lots of complexity (className
, style
) to Components. This rule only applies to Components (e.g. <Foo />
) and not DOM nodes (e.g. <div />
). (forbid-component-props)
// bad
<Hello className='foo' />
<Hello style={{color: 'red'}} />
// good
<Hello name='Joe' />
<div className='foo' />
6.4 Avoid using an array index as key
prop, prefer a stable ID. (no-array-index-key)
// bad
React.Children.map(this.props.children, (child, index) => (
React.cloneElement(child, { key: index })
))
Children.forEach(this.props.children, (child, index) => (
React.cloneElement(child, { key: index })
))
// good
React.Children.map(this.props.children, (child, index) => (
React.cloneElement(child, { key: child.id })
))
Children.forEach(this.props.children, (child, index) => (
React.cloneElement(child, { key: child.id })
))
6.5 Prevent passing of children as props, Children should always be actual children, not passed in as a prop.
When using JSX, the children should be nested between the opening and closing tags. When not using JSX, the children should be passed as additional arguments to React.createElement
. (no-children-prop)
// bad
<div children='Children' />
<MyComponent children={<AnotherComponent />} />
<MyComponent children={['Child 1', 'Child 2']} />
React.createElement("div", { children: 'Children' })
// good
<div>Children</div>
<MyComponent>Children</MyComponent>
<MyComponent>
<span>Child 1</span>
<span>Child 2</span>
</MyComponent>
React.createElement("div", {}, 'Children')
React.createElement("div", 'Child 1', 'Child 2')
6.6 Ensure that the value of the prop style
be an object or a variable that is an object. (style-prop-object)
// bad
<div style="color: 'red'" />
<div style={true} />
<Hello style={true} />
const styles = true;
<div style={styles} />
// good
<div style={{ color: "red" }} />
<Hello style={{ color: "red" }} />
const styles = { color: "red" };
<div style={styles} />
6.7 Ensures that any component or prop methods used to handle events are correctly prefixed. (jsx-handler-names)
// bad
<MyComponent handleChange={this.handleChange} />
<MyComponent onChange={this.componentChanged} />
// good
<MyComponent onChange={this.handleChange} />
<MyComponent onChange={this.props.onFoo} />
6.8 Avoid duplicate props which can cause unexpected behaviour in your application. (jsx-no-duplicate-props)
// bad
<Hello name="John" name="John" />;
// good
<Hello firstname="John" lastname="Doe" />;
Refs
7.1 Currently, two ways are supported by React to refer to components. The first way, providing a string identifier, is now considered legacy in the official documentation. The documentation now prefers a second method -- referring to components by setting a property on the this
object in the reference callback. (no-string-refs)
// bad
var Hello = createReactClass({
render: function() {
return <div ref="hello">Hello, world.</div>;
}
});
// good
var Hello = createReactClass({
componentDidMount: function() {
var component = this.hello;
},
render() {
return <div ref={(c) => { this.hello = c; }}>Hello, world.</div>;
}
});
7.2 When creating a JSX element that has an a
tag, it is often desired to have the link open in a new tab using the target='_blank'
attribute. Using this attribute unaccompanied by rel='noreferrer noopener'
, however, is a severe security vulnerability (see here for more details) This rules requires that you accompany target='_blank'
attributes with rel='noreferrer noopener'
. (jsx-no-target-blank)
// bad
var Hello = <a target='_blank' href="http://example.com/"></a>
var Hello = <a target='_blank' href={ dynamicLink }></a>
//good
var Hello = <p target='_blank'></p>
var Hello = <a target='_blank' rel='noopener noreferrer' href="http://example.com"></a>
var Hello = <a target='_blank' href="relative/path/in/the/host"></a>
var Hello = <a target='_blank' href="/absolute/path/in/the/host"></a>
var Hello = <a></a>
Ordering
8.1 When creating React components it is more convenient to always follow the same organisation for method order to help you easily find lifecycle methods, event handlers, etc. (sort-comp) The current Recommended Order For class components 1- Constructor 2- life cycle Methods e.g., componentDidMount, etc. 3- Static Methods e.g., handleSubmit, etc. 4- render function
// bad
var Hello = createReactClass({
render: function() {
return <div>Hello</div>;
},
displayName : 'Hello'
});
// good
var Hello = createReactClass({
displayName : 'Hello',
render: function() {
return <div>Hello</div>;
}
});
State
9.1 Prevent usage of this.state
inside setState
calls. Such usage of this.state
might result in errors when two state calls are called in batch and thus referencing old state and not the current state. (no-access-state-in-setstate)
// bad
function increment() {
this.setState({value: this.state.value + 1});
}
// good
function increment() {
this.setState(prevState => ({ value: prevState.value + 1}));
}
9.2 Avoid updating the state after a component mount or component update as it will trigger a second render()
call and can lead to property/layout thrashing. (no-will-update-set-state) & (no-did-mount-set-state)
// bad
var Hello = createReactClass({
componentDidMount: function() {
this.setState({
name: this.props.name.toUpperCase()
});
},
render: function() {
return <div>Hello {this.state.name}</div>;
}
});
var Hello = createReactClass({
componentDidUpdate: function() {
this.setState({
name: this.props.name.toUpperCase()
});
},
render: function() {
return <div>Hello {this.state.name}</div>;
}
});
// good
var Hello = createReactClass({
componentDidMount: function() {
this.onMount(function callback(newName) {
this.setState({
name: newName
});
});
},
render: function() {
return <div>Hello {this.state.name}</div>;
}
});
var Hello = createReactClass({
componentDidUpdate: function() {
this.props.onUpdate();
},
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
9.3 NEVER mutate this.state
directly, as calling setState()
afterwards may replace the mutation you made. Treat this.state
as if it were immutable. (no-direct-mutation-state)
// bad
var Hello = createReactClass({
componentDidMount: function() {
this.state.name = this.props.name.toUpperCase();
},
render: function() {
return <div>Hello {this.state.name}</div>;
}
});
class Hello extends React.Component {
constructor(props) {
super(props)
// Assign at instance creation time, not on a callback
doSomethingAsync(() => {
this.state = 'bad';
});
}
}
// good
var Hello = createReactClass({
componentDidMount: function() {
this.setState({
name: this.props.name.toUpperCase();
});
},
render: function() {
return <div>Hello {this.state.name}</div>;
}
});
class Hello extends React.Component {
constructor(props) {
super(props)
this.state = {
foo: 'bar',
}
}
}
9.4 Avoid updating the state during the componentWillUpdate step as it can lead to indeterminate component state and is not allowed. (no-will-update-set-state)
// bad
var Hello = createReactClass({
componentWillUpdate: function() {
this.setState({
name: this.props.name.toUpperCase()
});
},
render: function() {
return <div>Hello {this.state.name}</div>;
}
});
// good
var Hello = createReactClass({
componentWillUpdate: function() {
this.props.prepareHandler();
},
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
Styles
10.1 Always use double quotes (") for JSX attributes. (jsx-quotes)
// bad
<Foo bar='bar' />
<Foo style={{ left: '20px' }} />
// good
<Foo bar="bar" />
<Foo style={{ left: "20px" }} />