为什么JSX道具不应该使用箭头函数或绑定? [英] Why shouldn't JSX props use arrow functions or bind?

查看:186
本文介绍了为什么JSX道具不应该使用箭头函数或绑定?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用我的React应用程序运行lint,并且收到此错误:

I'm running lint with my React app, and I receive this error:

error    JSX props should not use arrow functions        react/jsx-no-bind

这就是我运行箭头函数的地方(里面) onClick ):

And this is where I'm running the arrow function (inside 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>
))}

这是一种应该避免的不良做法吗?什么是最好的方法?

Is this a bad practice that should be avoided? And what's the best way to do it?

推荐答案

为什么你不应该在JSX道具中使用内联箭头函数

在JSX中使用箭头函数或绑定是一种伤害性能的不良做法,因为在每次渲染时都会重新创建该函数。

Using arrow functions or binding in JSX is a bad practice that hurts performance, because the function is recreated on each render.


  1. 每当创建一个函数时,前一个函数都是垃圾收集的。重新渲染许多元素可能会在动画中创建jank。

  1. Whenever a function is created, the previous function is garbage collected. Rerendering many elements might create jank in animations.

使用内联箭头函数将导致 PureComponent s,以及在 shouldComponentUpdate 方法中使用 shallowCompare 的组件,无论如何都要重新渲染。由于每次都会重新创建箭头函数prop,浅层比较会将其识别为对prop的更改,组件将重新渲染。

Using an inline arrow function will cause PureComponents, and components that use shallowCompare in the shouldComponentUpdate method to rerender anyway. Since the arrow function prop is recreated each time, the shallow compare will identify it as a change to a prop, and the component will rerender.

正如您在以下2个示例中所看到的 - 当我们使用内联箭头功能时,每次都会重新呈现< Button> 组件(控制台显示''渲染按钮'文本)。

As you can see in the following 2 examples - when we use inline arrow function, the <Button> component is rerendered each time (the console shows the 'render button' text).

示例1 - PureComponent 不带内联处理程序

Example 1 - PureComponent without inline handler

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

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

示例2 - PureComponent with 内联处理程序

Example 2 - PureComponent with inline handler

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

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

将方法绑定到没有内联箭头函数

Binding methods to this without inlining arrow functions


  1. 在构造函数中手动绑定方法:

  1. Binding the method manually in the constructor:

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


  • 使用提案类字段,带有箭头功能。由于这是第3阶段提案,您需要添加第3阶段预设类属性转换为您的babel配置。

  • Binding a method using the proposal-class-fields with an arrow function. As this is a stage 3 proposal, you'll need to add the Stage 3 preset or the Class properties transform to your babel configuration.

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


  • 这篇关于为什么JSX道具不应该使用箭头函数或绑定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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