Kad*_*BOT 92 javascript jsx ecmascript-6 reactjs arrow-functions
我正在使用我的React app运行lint,我收到此错误:
error JSX props should not use arrow functions react/jsx-no-bind
Run Code Online (Sandbox Code Playgroud)
这就是我正在运行箭头功能(内部onClick)的地方:
{this.state.photos.map(tile => (
<span key={tile.img}>
<Checkbox
defaultChecked={tile.checked}
onCheck={() => this.selectPicture(tile)}
style={{position: 'absolute', zIndex: 99, padding: 5, backgroundColor: 'rgba(255, 255, 255, 0.72)'}}
/>
<GridTile
title={tile.title}
subtitle={<span>by <b>{tile.author}</b></span>}
actionIcon={<IconButton onClick={() => this.handleDelete(tile)}><Delete color="white"/></IconButton>}
>
<img onClick={() => this.handleOpen(tile.img)} src={tile.img} style={{cursor: 'pointer'}}/>
</GridTile>
</span>
))}
Run Code Online (Sandbox Code Playgroud)
这是一个应该避免的不良做法吗?什么是最好的方法呢?
Ori*_*ori 151
为什么你不应该在JSX道具中使用内联箭头函数
在JSX中使用箭头函数或绑定是一种伤害性能的不良做法,因为在每次渲染时都会重新创建该函数.
无论何时创建函数,前一个函数都是垃圾收集的.重新渲染许多元素可能会在动画中创建jank.
使用在线箭头功能会引起PureComponents,而使用的组件shallowCompare在shouldComponentUpdate方法无论如何重新呈现.由于每次都会重新创建箭头函数prop,因此浅层比较会将其识别为对prop的更改,并且该组件将重新渲染.
正如您在以下2个示例中所看到的 - 当我们使用内联箭头函数时,<Button>每次都会重新呈现组件(控制台显示"渲染按钮"文本).
示例1 - 没有内联处理程序的PureComponent
class Button extends React.PureComponent {
render() {
const { onClick } = this.props;
console.log('render button');
return (
<button onClick={ onClick }>Click</button>
);
}
}
class Parent extends React.Component {
state = {
counter: 0
}
onClick = () => this.setState((prevState) => ({
counter: prevState.counter + 1
}));
render() {
const { counter } = this.state;
return (
<div>
<Button onClick={ this.onClick } />
<div>{ counter }</div>
</div>
);
}
}
ReactDOM.render(
<Parent />,
document.getElementById('root')
);Run Code Online (Sandbox Code Playgroud)
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<div id="root"></div>Run Code Online (Sandbox Code Playgroud)
示例2 - 具有内联处理程序的PureComponent
class Button extends React.PureComponent {
render() {
const { onClick } = this.props;
console.log('render button');
return (
<button onClick={ onClick }>Click</button>
);
}
}
class Parent extends React.Component {
state = {
counter: 0
}
render() {
const { counter } = this.state;
return (
<div>
<Button onClick={ () => this.setState((prevState) => ({
counter: prevState.counter + 1
})) } />
<div>{ counter }</div>
</div>
);
}
}
ReactDOM.render(
<Parent />,
document.getElementById('root')
);Run Code Online (Sandbox Code Playgroud)
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<div id="root"></div>Run Code Online (Sandbox Code Playgroud)
绑定方法到this没有内联箭头函数
在构造函数中手动绑定方法:
class Button extends React.Component {
constructor(props, context) {
super(props, context);
this.cb = this.cb.bind(this);
}
cb() {
}
render() {
return (
<button onClick={ this.cb }>Click</button>
);
}
}
Run Code Online (Sandbox Code Playgroud)使用投标类字段和箭头函数绑定方法.由于这是第3阶段提案,因此您需要将Stage 3预设或Class属性转换添加到babel配置中.
class Button extends React.Component {
cb = () => { // the class property is initialized with an arrow function that binds this to the class
}
render() {
return (
<button onClick={ this.cb }>Click</button>
);
}
}
Run Code Online (Sandbox Code Playgroud)这是因为如果在JSX属性中使用,箭头函数显然将在每个渲染上创建函数的新实例.这可能会对垃圾收集器造成巨大压力,并且还会阻碍浏览器优化任何"热路径",因为函数将被丢弃而不是重用.
你可以在https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md看到整个解释和更多信息.
使用这样的内联函数非常好。linting 规则已经过时。
这个规则是在箭头函数不那么常见并且人们使用 .bind(this) 的时候开始的,这曾经很慢。性能问题已在 Chrome 49 中修复。
请注意不要将内联函数作为道具传递给子组件。
React Router 的作者 Ryan Florence 对此写了一篇很棒的文章:
https://cdb.reacttraining.com/react-inline-functions-and-performance-bdff784f5578
大多数情况下,因为内联函数会破坏优化组件的记忆:
传统上,React 中内联函数的性能问题与在每个渲染上传递新回调如何破坏
shouldComponentUpdate子组件中的优化有关。(文档)
它不是额外的函数创建成本:
性能问题
Function.prototype.bind在这里得到修复,箭头函数要么是原生的,要么被 babel 转译为普通函数;在这两种情况下,我们都可以假设它并不慢。(反应训练)我相信声称函数创建成本高昂的人总是被误导(React 团队从未说过这一点)。(推文)
react/jsx-no-bind规则什么时候有用?您要确保记忆化的组件按预期工作:
React.memo (对于功能组件)PureComponent或自定义shouldComponentUpdate(用于类组件)通过遵守此规则,传递稳定的函数对象引用。所以当之前的 props 没有改变时,上面的组件可以通过防止重新渲染来优化性能。
类:将处理程序定义为方法或用于绑定的类属性this。
挂钩:使用useCallback.
在很多情况下,内联函数使用起来非常方便,而且在性能要求方面绝对没问题。不幸的是,这条规则不能仅限于记忆化的组件类型。如果您仍然想全面使用它,您可以例如为简单的 DOM 节点禁用它:
rules: {
"react/jsx-no-bind": [ "error", { ignoreDOMComponents: true } ],
}
const Comp = () => <span onClick={() => console.log("Hello!")} />; // no warning
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
37706 次 |
| 最近记录: |