使用mapDispatchToProps避免无阴影夹板错误

时间:2016-06-07 14:53:31

标签: javascript reactjs redux eslint react-redux

我有以下组件在no-shadow FilterButton上触发props ESlint错误。

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


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

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

如何在保留mapDispatchToProps和ESlint规则的简洁语法的同时避免警告?

我知道我可以添加注释来抑制警告,但是对每个组件执行此操作似乎都是多余且乏味的。

6 个答案:

答案 0 :(得分:119)

这里有四个选项:

1。禁用规则。

<强>为什么吗

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

为什么不呢?

使用react-redux时,无阴影规则有助于防止出现非常常见的错误。也就是说,尝试调用原始的,未连接的操作(不会自动调度)。

换句话说,如果你不是使用解构并从道具中抓取动作,setFilter()就不会调度动作(因为你直接调用导入的动作) ,而不是通过props.setFilter()通过道具调用关联的动作,react-redux会自动为您调度。

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

如何吗

eslintConfig文件中添加package.json属性为one way to do this

"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 / this.props前置您的所有操作都是重复的(如果您要对所有其他非操作道具进行解构,则不一致)。

如何?

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

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

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

4。导入整个模块。

<强>为什么吗

简明扼要。

为什么不呢?

其他开发人员(或您未来的自己)可能无法理解正在发生的事情。根据您关注的风格指南,您可能会违反no-wildcard-imports rule

如何吗

如果您只是从一个模块传递动作创建者:

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

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

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

如果您要传递多个模块,请使用object destructuring with rest syntax

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);

答案 1 :(得分:7)

第五种选择:

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

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

<强>为什么吗

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

为什么不呢?

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

答案 2 :(得分:3)

第六个选项。

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行为。

答案 3 :(得分:2)

我调整了4.,实现了我想称呼的选项8。

8。以其他名称导入方法

为什么?

它具有与导入整个模块相同的优点,但不会与其他规则冲突,例如Do not use wildcard imports(airbnb)

为什么不呢?

它添加了不必要的变量声明,可能会引起混乱。

如何?

对于单方法案例

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

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

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

答案 4 :(得分:1)

在v7.1.0中添加了新的enter image description here之后,您就可以完全删除变量和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;

答案 5 :(得分:0)

选项7 ...

7。使用容器组件

为什么?

这是known pattern,您将获得额外的好处,那就是将组件与redux存储区解耦,从而使它们更易于重用。

为什么不呢?

您现在每个组件需要两个文件。

如何?

// FilterButton.jsx

export default function FilterButton({ setFilter }) {
  return (
    <button onClick={setFilter}>Click</button>
  );
}
// FilterButtonRedux.jsx

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

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