使用 mapDispatchToProps 避免 no-shadow eslint 错误
Avoid no-shadow eslint error with mapDispatchToProps
我有以下组件在 FilterButton
props
上触发 no-shadow
ESlint 错误。
import { setFilter } from '../actions/filter';
function FilterButton({ setFilter }) {
return (
<button onClick={setFilter}>Click</button>
);
}
export default connect(null, { setFilter })(FilterButton);
如何在保持 mapDispatchToProps
的简洁语法和 ESlint 规则的同时避免警告?
我知道我可以添加评论来抑制警告,但对每个组件都这样做似乎是多余且乏味的。
这里有四个选项:
1。禁用规则。
为什么?
这是避免 ESLint 错误的最简单方法。
为什么不呢?
no-shadow 规则有助于防止在使用 react-redux
时出现一个非常常见的错误。也就是说,尝试调用原始的、未连接的操作(不会自动调度)。
换句话说,如果你没有使用解构并从 props 中获取动作,setFilter()
将不会调度动作(因为你会调用直接导入操作,而不是通过 props.setFilter()
通过 props 调用连接的操作,react-redux
会自动为您调度)。
通过清理 variable shadowing,您 and/or 您的 IDE 更有可能发现错误。
怎么办?
将 eslintConfig
属性 添加到您的 package.json
文件是 one way to do this。
"eslintConfig": {
"rules": {
"no-shadow": "off",
}
}
2。将变量传递给 connect()
.
时重新分配变量
为什么?
您受益于 no-shadow 规则的安全性,而且,如果您选择遵守命名约定,那是非常明确的。
为什么不呢?
它介绍了样板文件。
如果您不使用命名约定,您现在必须为每个操作想出备用名称(仍然有意义)。并且相同的操作可能会在组件之间以不同的方式命名,这使得熟悉操作本身变得更加困难。
如果您使用命名约定,名称会变得又长又重复。
怎么办?
没有命名约定:
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
/this.props
为您的所有动作添加前缀是重复的(如果您正在解构所有其他 non-action 道具,则不一致)。
怎么办?
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 简洁语法的偏好,不妨使用隐式 return:
抛出箭头函数
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规则的方法可以用于多行代码。如果您传递更多参数并将它们分成多行代码,它会很有用。
为什么?
对于某些用例来说,这是一个简单且合适的选项(例如,您的 team/organization 使用特定的 es-lint 设置,并且 discouraged/forbidden 可以修改这些设置)。
它禁用代码行中的 es-lint 错误,但不影响 mapDispatchToProps
语法,并且该规则在代码行之外仍然完全有效。
为什么不呢?
您不希望或被禁止使用此类注释来膨胀您的代码。
您不想或被禁止影响 es-lint 行为。
选项 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);
我调整了 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);
随着 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;
我有以下组件在 FilterButton
props
上触发 no-shadow
ESlint 错误。
import { setFilter } from '../actions/filter';
function FilterButton({ setFilter }) {
return (
<button onClick={setFilter}>Click</button>
);
}
export default connect(null, { setFilter })(FilterButton);
如何在保持 mapDispatchToProps
的简洁语法和 ESlint 规则的同时避免警告?
我知道我可以添加评论来抑制警告,但对每个组件都这样做似乎是多余且乏味的。
这里有四个选项:
1。禁用规则。
为什么?
这是避免 ESLint 错误的最简单方法。
为什么不呢?
no-shadow 规则有助于防止在使用 react-redux
时出现一个非常常见的错误。也就是说,尝试调用原始的、未连接的操作(不会自动调度)。
换句话说,如果你没有使用解构并从 props 中获取动作,setFilter()
将不会调度动作(因为你会调用直接导入操作,而不是通过 props.setFilter()
通过 props 调用连接的操作,react-redux
会自动为您调度)。
通过清理 variable shadowing,您 and/or 您的 IDE 更有可能发现错误。
怎么办?
将 eslintConfig
属性 添加到您的 package.json
文件是 one way to do this。
"eslintConfig": {
"rules": {
"no-shadow": "off",
}
}
2。将变量传递给 connect()
.
时重新分配变量
为什么?
您受益于 no-shadow 规则的安全性,而且,如果您选择遵守命名约定,那是非常明确的。
为什么不呢?
它介绍了样板文件。
如果您不使用命名约定,您现在必须为每个操作想出备用名称(仍然有意义)。并且相同的操作可能会在组件之间以不同的方式命名,这使得熟悉操作本身变得更加困难。
如果您使用命名约定,名称会变得又长又重复。
怎么办?
没有命名约定:
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
/this.props
为您的所有动作添加前缀是重复的(如果您正在解构所有其他 non-action 道具,则不一致)。
怎么办?
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 简洁语法的偏好,不妨使用隐式 return:
抛出箭头函数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规则的方法可以用于多行代码。如果您传递更多参数并将它们分成多行代码,它会很有用。
为什么?
对于某些用例来说,这是一个简单且合适的选项(例如,您的 team/organization 使用特定的 es-lint 设置,并且 discouraged/forbidden 可以修改这些设置)。
它禁用代码行中的 es-lint 错误,但不影响 mapDispatchToProps
语法,并且该规则在代码行之外仍然完全有效。
为什么不呢?
您不希望或被禁止使用此类注释来膨胀您的代码。 您不想或被禁止影响 es-lint 行为。
选项 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);
我调整了 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);
随着 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;