使用 mapDispatchToProps 避免无阴影 eslint 错误

IT技术 javascript reactjs redux eslint react-redux
2021-04-28 23:58:46

我有以下组件会no-shadowFilterButton props.

import { setFilter } from '../actions/filter';


function FilterButton({ setFilter }) {
  return (
    <button onClick={setFilter}>Click</button>
  );
}

export default connect(null, { setFilter })(FilterButton);

如何在保持mapDispatchToPropsESlint 规则的简洁语法的同时避免警告

我知道我可以添加注释来抑制警告,但对每个组件都这样做似乎是多余和乏味的。

4个回答

这里有四个选项:

1. 禁用规则。

为什么?

这是避免 ESLint 错误的最简单方法。

为什么不?

无阴影规则有助于防止使用react-redux. 也就是说,尝试调用原始的、未连接的操作(不会自动分派)。

换句话说,如果您不使用解构并从 props 中获取动作,则setFilter()不会调度该动作(因为您将直接调用导入的动作,而不是通过 props via 调用连接的动作props.setFilter(),后者会react-redux自动为您调度)。

通过清理变量 shadowing,您和/或您的 IDE 更有可能发现错误。

如何?

文件中添加eslintConfig属性package.json实现此目的的一种方法

"eslintConfig": {
    "rules": {
      "no-shadow": "off",
    }
  }

2. 将变量传入时重新赋值connect()

为什么?

您受益于无影子规则的安全性,并且,如果您选择遵守命名约定,则它非常明确。

为什么不?

它引入了样板。

如果您不使用命名约定,您现在必须为每个操作想出替代名称(仍然有意义)。而且很可能相同的动作在不同的组件中会以不同的方式命名,这使得熟悉动作本身变得更加困难。

如果您确实使用命名约定,名称会变得冗长且重复。

如何?

没有命名约定:

import { setFilter } from '../actions/filter';

function FilterButton({ filter }) {
  return (
    <button onClick={filter}>Click</button>
  );
}

export default connect(null, { filter: setFilter })(FilterButton);

使用命名约定:

import { setFilter, clearFilter } from '../actions/filter';

function FilterButton({ setFilterConnect, clearFilterConnect }) {
  return (
    <button onClick={setFilterConnect} onBlur={clearFilterConnect}>Click</button>
  );
}

export default connect(null, {
  setFilterConnect: setFilter,
  clearFilterConnect: clearFilter,
})(FilterButton);

3. 不要用props来解构动作。

为什么?

通过显式使用 props 对象的方法,您无需担心开始时的阴影。

为什么不?

props/预先设置所有动作this.props是重复的(如果您正在解构所有其他非动作props,则不一致)。

如何?

import { setFilter } from '../actions/filter';

function FilterButton(props) {
  return (
    <button onClick={props.setFilter}>Click</button>
  );
}

export default connect(null, { setFilter })(FilterButton);

4. 导入整个module。

为什么?

很简洁。

为什么不?

其他开发人员(或您未来的自己)可能无法理解正在发生的事情。根据您遵循的样式指南,您可能会违反no-wildcard-imports 规则

如何?

如果您只是从一个module传入动作创建者:

import * as actions from '../actions/filter';

function FilterButton({ setFilter }) {
  return (
    <button onClick={setFilter}>Click</button>
  );
}

export default connect(null, actions)(FilterButton);

如果您传入多个module,请使用带有其余语法的对象解构

import * as filterActions from '../actions/filter';
import * as otherActions from '../actions/other';

// all exported actions from the two imported files are now available as props
function FilterButton({ setFilter, clearFilter, setOther, clearOther }) {
  return (
    <button onClick={setFilter}>Click</button>
  );
}

export default connect(null, { ...filterActions, ...otherActions })(FilterButton);

既然你在评论中提到了 ES6 简洁语法的偏好,那么不妨在箭头函数中抛出一个隐式返回:

import * as actions from '../actions/filter';

const FilterButton = ({ setFilter }) => <button onClick={setFilter}>Click</button>;

export default connect(null, actions)(FilterButton);

第五个选项:

5. 通过eslintrc规则允许特定的例外

module.exports = {
  rules: {
    'no-shadow': [
      'error',
      {
        allow: ['setFilter'],
      },
    ],
  }
}

为什么?

您不想要变量阴影,但在某些情况下无法绕过它。

为什么不?

真的不希望代码库中存在变量阴影。😝

选项六。

6. 禁用特定代码行的 es-lint 规则

import { setFilter } from '../actions/filter';


// eslint-disable-next-line no-shadow
function FilterButton({ setFilter }) {
  return (
    <button onClick={setFilter}>Click</button>
  );
}

export default connect(null, { setFilter })(FilterButton);

或者

import { setFilter } from '../actions/filter';


/* eslint-disable no-shadow */
function FilterButton({ setFilter }) {
/* es-lint-enable */
  return (
    <button onClick={setFilter}>Click</button>
  );
}

export default connect(null, { setFilter })(FilterButton);

与第一种不同,第二种暂时禁用 es-lint 规则的方法可以用于多行代码。如果您传递更多参数并将它们分成多行代码,它会很有用。

为什么?

对于某些用例(例如,您的团队/组织使用特定的 es-lint 设置,并且不鼓励/禁止修改这些设置),这是一个简单且合适的选项。它禁用代码行中的 es-lint 错误,但不影响mapDispatchToProps语法,并且规则在代码行之外仍然完全有效。

为什么不?

您不希望或被禁止使用此类注释来膨胀您的代码。您不希望或被禁止影响 es-lint 行为。

使用v7.1.0 中添加的新Hooks API,您可以mapDispatchToProps完全摆脱变量

import { useDispatch } from 'react-redux'
import { setFilter } from '../actions/filter';

function FilterButton() {
  const dispatch = useDispatch()
  return (
    <button onClick={dispatch(setFilter())}>Click</button>
  );
}

export default FilterButton;