React 代码风格指南

react/jsx-curly-brace-presenceopen in new window

禁止 jsx 中使用无用的引号

// bad
<App prop={'foo'}>{'Hello World'}</App>;
// good
<App prop="foo">Hello World</App>;

react/jsx-fragmentsopen in new window

必须使用 <></> 而不是 React.Fragment

// bad
<React.Fragment></React.Fragment>;
// good
<></>;

<></> 不需要额外引入 Fragment 组件

react/jsx-keyopen in new window

数组中的 jsx 必须有 key

// bad
<ul>
    {[1, 2, 3].map((value) => (
        <li>{value}</li>
    ))}
</ul>;
<div>
    {[1, 2, 3].map((value) => (
        <>{value}</>
    ))}
</div>;
// good
<ul>
    {[1, 2, 3].map((value) => (
        <li key={value}>{value}</li>
    ))}
</ul>;
<div>
    {[1, 2, 3].map((value) => (
        <React.Fragment key={value}>{value}</React.Fragment>
    ))}
</div>;

react/jsx-no-comment-textnodesopen in new window

禁止在 jsx 中使用像注释的字符串

// bad
<div>// empty div</div>;
<div>/* empty div */</div>;

// good
<div>{/* empty div */}</div>;
<div /* empty div */ />;

react/jsx-no-duplicate-propsopen in new window

禁止出现重复的 props

// bad
<Foo name="foo" name="bar"/>;
// good
<Foo name="foo"/>;

react/jsx-no-undefopen in new window

禁止使用未定义的组件

// bad
<Foo/>;
// good
import Foo from './Foo';

<Foo/>;

react/jsx-pascal-caseopen in new window

禁止使用 pascal 格式的组件

// bad
<FOO/>;
<FOO_BAR/>;
// good
<Foo/>;
<FooBar/>;

react/jsx-uses-reactopen in new window

修复 React 被误报为未使用的变量的问题(仅在开启 no-unused-vars 时有效)

// bad
/* eslint no-unused-vars: "error", react/jsx-uses-react: "off" */
import React from 'react';

<div/>;
// good
/* eslint no-unused-vars: "error" */
import React from 'react';

<div/>;

react/jsx-uses-varsopen in new window

已定义的组件必须使用

// bad
/* eslint no-unused-vars: "error" */
import Foo from './Foo';
// good
/* eslint no-unused-vars: "error" */
import Foo from './Foo';

<Foo/>;

react/no-children-propopen in new window

禁止将 children 作为一个 prop

// bad
<div children="Hello World"/>;
<Foo children={<Bar/>}/>;
// good
<div>Hello World</div>;
<Foo>
    <Bar/>
</Foo>;

react/no-danger-with-childrenopen in new window

禁止在使用了 dangerouslySetInnerHTML 的组件内添加 children

// bad
<div dangerouslySetInnerHTML={{__html: 'Foo'}}>Hello World</div>;
// good
<div dangerouslySetInnerHTML={{__html: 'Foo'}}/>;
<div>Hello World</div>;

react/no-deprecatedopen in new window

禁止使用已废弃的 api

// bad
React.render(<Foo/>, app);

class Foo extends React.Component {
    componentWillMount() {
    }

    componentWillReceiveProps() {
    }

    componentWillUpdate() {
    }
}
// good
ReactDOM.render(<Foo/>, app);

class Foo extends React.Component {
}

react/no-did-update-set-stateopen in new window

禁止在 componentDidUpdate 里使用 setState

// bad
class Foo extends React.Component {
    componentDidUpdate() {
        this.setState();
    }
}
// good
class Foo extends React.Component {
    componentDidUpdate() {
    }
}

react/no-direct-mutation-stateopen in new window

禁止直接修改 this.state

// bad
class Foo extends React.Component {
    componentDidMount() {
        this.state.name = 'foo';
    }
}
// good
class Foo extends React.Component {
    constructor() {
        this.state = {
            name: 'foo'
        };
    }
}

react/no-find-dom-nodeopen in new window

禁止使用 findDOMNode

// bad
class Foo extends React.Component {
    componentDidMount() {
        const root = findDOMNode(this);
    }

    render() {
        return <div/>;
    }
}
// good
class Foo extends React.Component {
    constructor() {
        this.myRef = React.createRef();
    }

    render() {
        return <div ref={this.myRef}/>;
    }
}

react/no-is-mountedopen in new window

禁止使用 isMounted

// bad
class Foo extends React.Component {
    updateName() {
        if (this.isMounted()) {
            this.setState({});
        }
    }
}
// good
class Foo extends React.Component {
    updateName() {
        if (this._isMounted) {
            this.setState({});
        }
    }
}

它是已废弃的语法

react/no-redundant-should-component-updateopen in new window

禁止在 React.PureComponent 中使用 shouldComponentUpdate

// bad
class Foo extends React.PureComponent {
    shouldComponentUpdate() {
    }
}
// good
class Foo extends React.Component {
    shouldComponentUpdate() {
    }
}

react/no-render-return-valueopen in new window

禁止使用 ReactDOM.render 的返回值

// bad
const app = ReactDOM.render(<App/>, document.getElementById('app'));
// good
ReactDOM.render(<App/>, document.getElementById('app'));

react/no-string-refsopen in new window

禁止使用字符串 ref

// bad
class Foo {
    componentDidMount() {
        console.log(this.refs.foo);
    }

    render() {
        return <div ref="foo"/>;
    }
}
// good
import {useRef, useEffect} from 'react';

function Foo() {
    const foo = useRef(null);
    useEffect(() => {
        console.log(foo);
    });
    return <div ref={foo}/>;
}

react/no-this-in-sfcopen in new window

禁止在函数组件中使用 this

// bad
function Foo() {
    return <div>{this.props.foo}</div>;
}
// good
function Foo(props) {
    return <div>{props.foo}</div>;
}

react/no-typosopen in new window

禁止组件的属性或生命周期大小写错误

// bad
class Foo extends React.Component {
    static defaultprops = {};

    componentdidupdate() {
    }
}
// good
class Foo extends React.Component {
    static defaultProps = {};

    componentDidUpdate() {
    }
}

react/no-unescaped-entitiesopen in new window

禁止在组件的内部存在未转义的 >, ", ' 或 }

// bad
<Foo>Hel>lo</Foo>;
// good
<Foo>Hel&amp;gt;lo</Foo>;

react/no-unknown-propertyopen in new window

禁止出现 HTML 中的属性,如 class

// bad
<div class="foo"/>;
// good
<div className="foo"/>;

react/no-unsafeopen in new window

禁止使用不安全的生命周期方法 componentWillMount, componentWillReceiveProps, componentWillUpdate

// bad
class Foo extends React.Component {
    componentWillMount() {
    }

    UNSAFE_componentWillMount() {
    }
}
// good
class Foo extends React.Component {
}

react/prefer-es6-classopen in new window

必须使用 Class 的形式创建组件

// bad
const Foo = createReactClass({
    render() {
        return <div/>;
    }
});
// good
class Foo extends React.Component {
    render() {
        return <div/>;
    }
}

react/require-render-returnopen in new window

render 方法中必须有返回值

// bad
class Foo extends React.Component {
    render() {
        <div/>;
    }
}
// good
class Foo extends React.Component {
    render() {
        return <div/>;
    }
}

react/self-closing-compopen in new window

组件内没有 children 时,必须使用自闭和写法

// bad
<Foo></Foo>;
<div></div>;
// good
<Foo>Not empty</Foo>;
<div>Not empty</div>;
<Bar/>;
<div/>;

react/sort-compopen in new window

组件内方法必须按照一定规则排序

// bad
class Foo extends React.Component {
    render() {
        return <div/>;
    }

    componentWillUnmount() {
    }

    componentDidMount() {
    }

    constructor() {
    }

    static defaultProps = {};
}
// good
class Foo extends React.Component {
    static defaultProps = {};

    constructor() {
    }

    componentDidMount() {
    }

    componentWillUnmount() {
    }

    render() {
        return <div/>;
    }
}

react/static-property-placementopen in new window

类的静态属性必须使用 static 关键字定义

// bad
class Foo extends React.Component {
}

Foo.defaultProps = {};
// good
class Foo extends React.Component {
    static defaultProps = {};
}

react/style-prop-objectopen in new window

style 属性的取值必须是 object

// bad
<div style="color: 'red'"/>;
// good
<div style={{color: 'red'}}/>;

react/void-dom-elements-no-childrenopen in new window

img, br 标签中禁止有 children

// bad
<img>foo</img>;
<br>bar</br>;
// good
<img/>;
<br/>;
<div>foo</div>;