# NCUHOME React 代码风格指南

# react/jsx-curly-brace-presence

禁止 jsx 中使用无用的引号

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

// good
<App prop="foo">Hello World</App>;

# react/jsx-fragments

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

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

// good
<></>;

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

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

# react/jsx-key

数组中的 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-textnodes

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

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


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

# react/jsx-no-duplicate-props

禁止出现重复的 props

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

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

# react/jsx-no-undef

禁止使用未定义的组件

// bad
<Foo />;

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

# react/jsx-pascal-case

禁止使用 pascal 格式的组件

// bad
<FOO />;
<FOO_BAR />;

// good
<Foo />;
<FooBar />;

# react/jsx-uses-react

修复 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-vars

已定义的组件必须使用

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

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

<Foo />;

# react/no-children-prop

禁止将 children 作为一个 prop

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

// good
<div>Hello World</div>;
<Foo>
    <Bar />
</Foo>;

# react/no-danger-with-children

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

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

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

# react/no-deprecated

禁止使用已废弃的 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-state

禁止在 componentDidUpdate 里使用 setState

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

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

# react/no-direct-mutation-state

禁止直接修改 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-node

禁止使用 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-mounted

禁止使用 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-update

禁止在 React.PureComponent 中使用 shouldComponentUpdate

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

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

# react/no-render-return-value

禁止使用 ReactDOM.render 的返回值

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

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

# react/no-string-refs

禁止使用字符串 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-sfc

禁止在函数组件中使用 this

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

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

# react/no-typos

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

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

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

# react/no-unescaped-entities

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

// bad
<Foo>Hel>lo</Foo>;

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

# react/no-unknown-property

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

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

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

# react/no-unsafe

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

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

// good
class Foo extends React.Component {}

# react/prefer-es6-class

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

// bad
const Foo = createReactClass({
    render() {
        return <div />;
    }
});

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

# react/require-render-return

render 方法中必须有返回值

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

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

# react/self-closing-comp

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

// bad
<Foo></Foo>;
<div></div>;

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

# react/sort-comp

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

// 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-placement

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

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

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

# react/style-prop-object

style 属性的取值必须是 object

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

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

# react/void-dom-elements-no-children

img, br 标签中禁止有 children

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

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