使用 mapDispatchToProps 避免无阴影 eslint 错误 [英] Avoid no-shadow eslint error with mapDispatchToProps

查看:28
本文介绍了使用 mapDispatchToProps 避免无阴影 eslint 错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

import { setFilter } from '../actions/filter';功能过滤器按钮({ setFilter }){返回 (<button onClick={setFilter}>点击</button>);}导出默认连接(null, { setFilter })(FilterButton);

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

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

解决方案

这里有四个选项:

1.禁用规则.

为什么?

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

为什么不呢?

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

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

通过清理变量阴影,您和/或您的 IDE 更有可能获得关于错误.

如何?

eslintConfig 属性添加到您的 package.json 文件是 一种方法.

"eslintConfig": {规则":{"无阴影": "关闭",}}

2.将变量传递给 connect() 时重新分配变量.

为什么?

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

为什么不呢?

它引入了样板.

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

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

如何?

没有命名约定:

import { setFilter } from '../actions/filter';功能过滤器按钮({过滤器}){返回 (<button onClick={filter}>Click</button>);}export default connect(null, { filter: setFilter })(FilterButton);

使用命名约定:

import { setFilter, clearFilter } from '../actions/filter';function FilterButton({ setFilterConnect, clearFilterConnect }) {返回 (<button onClick={setFilterConnect} onBlur={clearFilterConnect}>点击</button>);}导出默认连接(空,{设置过滤器连接:设置过滤器,清除过滤器连接:清除过滤器,})(过滤按钮);

3.不要从道具中解构动作.

为什么?

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

为什么不呢?

使用 props/this.props 预先准备所有动作是重复的(如果您正在解构所有其他非动作道具,则不一致).

怎么样?

import { setFilter } from '../actions/filter';功能过滤器按钮(道具){返回 (<button onClick={props.setFilter}>点击</button>);}导出默认连接(null, { setFilter })(FilterButton);

4.导入整个模块.

为什么?

简洁.

为什么不呢?

其他开发者(或您未来的自己)可能无法理解正在发生的事情.根据您遵循的风格指南,您可能会打破 no-wildcard-导入规则.

如何?

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

import * as actions from '../actions/filter';功能过滤器按钮({ setFilter }){返回 (<button onClick={setFilter}>点击</button>);}导出默认连接(空,动作)(过滤器按钮);

如果您传入多个模块,请使用 使用rest语法进行对象解构:

import * as filterActions from '../actions/filter';import * as otherActions from '../actions/other';//从两个导入的文件中导出的所有操作现在都可以作为道具使用function FilterButton({ setFilter, clearFilter, setOther, clearOther }) {返回 (<button onClick={setFilter}>点击</button>);}export default connect(null, { ...filterActions, ...otherActions })(FilterButton);

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

import * as actions from '../actions/filter';const FilterButton = ({ setFilter }) =><button onClick={setFilter}>Click</button>;导出默认连接(空,动作)(过滤器按钮);

I have the following component that triggers a no-shadow ESlint error on the FilterButton props.

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


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

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

How can I avoid the warning while keeping both the concise syntax of mapDispatchToProps and the ESlint rule?

I know I can add a comment to suppress the warning but doing it for every components seems redundant and tedious.

解决方案

There are four options here:

1. Disable the rule.

Why?

It's the easiest way to avoid the ESLint error.

Why Not?

The no-shadow rule helps to prevent a very common bug when using react-redux. That is, attempting to invoke the raw, unconnected action (which does not automatically get dispatched).

In other words, if you were not using destructuring and grabbing the action from props, setFilter() would not dispatch the action (because you'd be invoking the imported action directly, as opposed to invoking the connected action through props via props.setFilter(), which react-redux automatically dispatches for you).

By cleaning up variable shadowing, you and/or your IDE are more likely to pick up on the error.

How?

Adding a eslintConfig property to your package.json file is one way to do this.

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

2. Reassign the variable when passing it into connect().

Why?

You benefit from the safety of the no-shadow rule, and, if you choose to adhere to a naming convention, it's very explicit.

Why Not?

It introduces boilerplate.

If you do not use a naming convention, you now have to come up with alternate names (that still make sense) for every action. And chances are that the same actions will be named differently across components, making it harder to become familiar with the actions themselves.

If you do use a naming convention, names become long and repetitive.

How?

Without naming convention:

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

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

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

With naming convention:

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. Don't destructure actions off of props.

Why?

By explicitly using the method off of the props object, you don't need to worry about shadowing to begin with.

Why Not?

Prepending all of your actions with props/this.props is repetitive (and inconsistent if you're destructuring all of your other non-action props).

How?

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

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

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

4. Import the entire module.

Why?

It's concise.

Why Not?

Other developers (or your future self) may have trouble understanding what's going on. And depending on the style guide you're following, you might be breaking the no-wildcard-imports rule.

How?

If you're simply passing in action creators from one module:

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

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

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

If you're passing in multiple modules, use 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);

And since you mentioned a preference for ES6's concise syntax in the comments, might as well throw in the arrow function with an implicit return:

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

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

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

这篇关于使用 mapDispatchToProps 避免无阴影 eslint 错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆