为什么JSX道具不应该使用箭头功能 [英] Why JSX props should not use arrow functions

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

问题描述

我正在使用我的React应用程序,并收到此错误

 错误JSX道具不应使用箭头功能反应/ jsx-no-bind 

这是我运行箭头函数的地方(inClick ):

  {this.state.photos.map(tile =>(
< span key = tile.img}>
<复选框
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>
))}

这是不好的做法,应该避免吗?那么最好的方法是什么?

解决方案

为什么不应该在JSX props中使用内联箭头功能



在JSX中使用箭头函数或绑定是一个坏的做法,会损害性能,因为每个渲染功能都会重新创建。


  1. 无论何时创建一个函数,上一个函数都是垃圾回收的。使用内联箭头函数会导致 PureComponent s,这样可以在动画中创建多个元素。


  2. <以及 shouldComponentUpdate 方法中使用 shallowCompare 的组件,无论如何都要重新渲染。由于每次重新创建箭头功能,所以浅比较将会将其标识为对道具的更改,并且组件将重新安装。


正如您在以下2个例子中可以看到的那样 - 当我们使用内联箭头函数时,每次都会重新呈现< Button> 组件(控制台显示



示例1 - PureComponent 内联处理程序



  class Button extends React.PureComponent {render(){const {onClick} = this.props; console.log('render button'); return(< button onClick = {onClick}>点击< / 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 src =https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react.min.js>< / script> < script src =https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.min.js>< / script>< div id =root> ;< / div>  



示例2 - PureComponent with inline handler



  class Button extends React.PureComponent {render(){const {onClick} = this.props; console.log('render button'); return(< button onClick = {onClick}>点击< / button>); }} class Parent extends React.Component {state = {counter:0} render(){const {counter} = this.state; (< div>< Button onClick = { < / div>< / div>); }} ReactDOM.render(< Parent />,document.getElementById('root'));  

 < script src =https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react.min.js>< / script> < script src =https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.min.js>< / script>< div id =root> ;< / div>  



code>这个没有内联箭头函数


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

      class Button extends React.Component {
    constructor(props,context){
    超级(道具,上下文);

    this.cb = this.cb.bind(this);
    }

    cb(){

    }

    render(){
    return(
    &按钮onClick = {this.cb}>点击< / button>
    );
    }
    }


  2. 使用 proposal-class-fields ,带箭头功能。由于这是第2阶段提案,因此您需要添加第2阶段预设类属性转换到您的宝贝配置。 p>

      class Button extends React.Component {
    cb =()=> {//类属性初始化为一个箭头函数,将其绑定到类

    }

    render(){
    return(
    < ; button onClick = {this.cb}>点击< / button>
    );
    }
    }



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

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 and should be avoided? And what's the best way to do it?

解决方案

Why you shouldn't use inline arrow functions in JSX props

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

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

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

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

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 src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.min.js"></script>
<div id="root"></div>

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 src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.min.js"></script>
<div id="root"></div>

Binding methods to this without inlining arrow functions

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

  2. Binding a method using the proposal-class-fields with an arrow function. As this is a stage 2 proposal, you'll need to add the Stage 2 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天全站免登陆