解决似乎没有意义的ESLint / React / Redux(Airbnb配置)错误

时间:2018-02-14 16:52:29

标签: reactjs redux react-redux eslint eslint-config-airbnb

我正在研究使用ESLint(Airbnb配置)和React / Redux的原则。

以下代码是一个标准类型的React / Redux类,我写这篇文章是为了享受Airbnb所有的linting学科。

通过了解Airbnb的配置偏好,我已经解决了大部分掉毛错误,但是,我目前还有几个方面无法理解。这些是:

  1. 整个方法renderTableHeader()以红色标出,ESLint告诉我:
  2.   

    [eslint]期望'this'由类方法使用   'renderTableHeader'。 (class-methods-use-this)(JSX属性)   className:string   enter image description here

         

    没有其他方法有这个linting问题

    1. 我将一个从Redux状态的对象连接到props(包含我需要在这个类中迭代的许多键/对象)。 ESLint似乎并不喜欢我将对象从状态连接到道具......给我留言:
    2.   

      [eslint]禁止使用道具类型object(react / forbid-prop-types)   导入PropTypes

           

      enter image description here

      我的状态对象是一个包含许多引用用户对象的键的对象 - 所以我需要users作为对象。这是不好的做法吗?如果没有出现这个lint消息,我将如何连接一个要映射的对象?

      提前致谢...这是我的班级:

      import React, { Component } from 'react';
      import { bindActionCreators } from 'redux';
      import { connect } from 'react-redux';
      import PropTypes from 'prop-types';
      import _ from 'lodash';
      import { getUsers } from '../actions/getUsers';
      import setUserMarketingPref from '../actions/setUserMarketingPref';
      import { setFilter } from '../actions/setFilter';
      import TableRow from '../components/TableRow';
      import '../styles/styles.css';
      
      class AppContainer extends Component {
        componentDidMount() {
          this.props.getUsers();
        }
      
        renderTableHeader() {
          return (
            <div className="table__header">
              <div className="table__header--name">Name</div>
              <div className="table__header--gender">Gender</div>
              <div className="table__header--region">Region</div>
            </div>
          );
        }
      
        renderTable() {
          const { users, filterMode } = this.props;
          const usersView = filterMode ? _.omitBy(users, user => !user.checked) : users;
          return _.map(usersView, user => (
            <TableRow
              user={user}
              key={user.id}
              setUserMarketingPref={_.debounce(() => this.props.setUserMarketingPref(user.id), 100)}
            />
          ));
        }
      
        renderFilters() {
          return (
            <div className="table__buttons">
              <button
                id="marketing-other"
                className="table__other"
                onClick={e => this.props.setFilter(e.target.id)}
              >Other filter
              </button>
              <button
                id="marketing-none"
                className="table__no-marketing"
                onClick={e => this.props.setFilter(e.target.id)}
              >No marketing
              </button>
            </div>
          );
        }
      
        render() {
          if (!_.size(this.props.users)) {
            return null;
          }
          return (
            <div className="table__container">
              {this.renderTableHeader()}
              {this.renderTable()}
              {this.renderFilters()}
            </div>
          );
        }
      }
      
      const mapDispatchToProps = dispatch => bindActionCreators(
        {
          getUsers,
          setUserMarketingPref,
          setFilter,
        },
        dispatch,
      );
      
      const mapStateToProps = state => ({
        users: state.users,
        filter: state.filter,
        filterMode: state.marketing.filterMode,
      });
      
      AppContainer.defaultProps = {
        filterMode: false,
        getUsers: null,
        setUserMarketingPref: null,
        setFilter: null,
      };
      
      AppContainer.propTypes = {
        users: PropTypes.object,
        filterMode: PropTypes.bool,
        getUsers: PropTypes.func,
        setUserMarketingPref: PropTypes.func,
        setFilter: PropTypes.func,
      };
      
      export default connect(mapStateToProps, mapDispatchToProps)(AppContainer);
      

1 个答案:

答案 0 :(得分:7)

这两条规则涉及两个不同的事情

  

首先:预期&#39;这个&#39;由类方法&#39; renderTableHeader&#39;使用。 (class-methods-use-this)(JSX属性)   className:string

根据 documentation

如果类方法不使用它,有时可以将其作为静态函数。如果您确实将方法转换为静态函数,那么调用该特定方法的类的实例也必须转换为静态调用(MyClass.callStaticMethod())

另请注意,在上面的示例中,如果将方法切换为静态方法,则必须将调用静态方法(let a = new A(); a.sayHi();)的类的实例更新为静态调用(A.sayHi();)而不是让类的实例调用方法

如何避免此警告

exceptMethods选项允许您传递要忽略警告的方法名称数组。例如,您可能有一个来自外部库的规范要求您将方法覆盖为常规函数(而不是静态方法),并且不在函数体内使用它。在这种情况下,您可以在警告中添加要忽略的方法。

"class-methods-use-this": [<enabled>, { "exceptMethods": [<...exceptions>] }]
  

第二个:禁止支持类型对象(react / forbid-prop-types)导入PropTypes

定义非模糊的PropType是一种很好的做法,例如anyarrayobject,它们并没有清楚地告诉您实际上道具是什么类型。

根据 documentation

默认情况下,此规则可防止含有更多特定替代项的模糊prop类型(any,array,object),但如果需要,可以禁用任何prop类型。选择默认值是因为它们具有明显的替代品。任何东西都应该被替换。数组和对象可以分别替换为arrayOf和shape。

在你的情况下,说user是一个像

这样的对象
{
    id: 123,
    name: 'abc'
}

您可以将PropType定义为

AppContainer.propTypes = {
  users: PropTypes.shape({
    id: PropTypes.number,
    name: PropTypes.string
  }),,
  filterMode: PropTypes.bool,
  getUsers: PropTypes.func,
  setUserMarketingPref: PropTypes.func,
  setFilter: PropTypes.func,
};