当前位置: 首页 > 面试题库 >

为什么JSX道具不应该使用箭头功能或绑定?

干亮
2023-03-14
问题内容

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

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

这是我运行箭头功能(在里面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>
))}

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


问题答案:

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

在JSX中使用箭头函数或绑定是不利于性能的不良做法,因为该函数会在每个渲染器上重新创建。

  1. 每当创建一个函数时,就会对前一个函数进行垃圾回收。渲染许多元素可能会在动画中产生垃圾。

  2. 使用内联箭头功能将导致PureComponents和shallowCompareshouldComponentUpdate方法中使用的组件重新渲染。由于箭头函数prop每次都会重新创建,因此浅表比较会将其标识为对prop的更改,并且组件将重新呈现。

在下面的两个示例中可以看到-当我们使用嵌入式箭头功能时,<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')

);


<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

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>

this 不带内联箭头功能的绑定方法

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

    class Button extends React.Component {
    

    constructor(props, context) {
    super(props, context);

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

    }

    cb() {

    }

    render() {
    return (

    );
    }
    }

  2. 使用带有箭头功能的proposal-class-fields绑定方法。由于这是第3阶段的建议,因此您需要添加第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在这种情况下),则该子组件也会重新渲染。

示例1-具有内部回调的功能组件:

const { memo, useState } = React;



const Button = memo(({ onClick }) => console.log('render button') || (

  <button onClick={onClick}>Click</button>

));



const Parent = () => {

  const [counter, setCounter] = useState(0);



  const increment = () => setCounter(counter => counter + 1); // the function is recreated all the time



  return (

    <div>

      <Button onClick={increment} />



      <div>{counter}</div>

    </div>

  );

}



ReactDOM.render(

  <Parent />,

  document.getElementById('root')

);


<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>

<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>



<div id="root"></div>

为了解决这个问题,我们可以使用useCallback()hook来包装回调,并将依赖项设置为一个空数组。

注意:useState生成函数接受更新器功能,其提供当前状态。这样,我们无需将当前状态设置为的依赖项useCallback

示例2-具有内部回调的函数组件,该内部回调包装有useCallback:

const { memo, useState, useCallback } = React;



const Button = memo(({ onClick }) => console.log('render button') || (

  <button onClick={onClick}>Click</button>

));



const Parent = () => {

  const [counter, setCounter] = useState(0);



  const increment = useCallback(() => setCounter(counter => counter + 1), []);



  return (

    <div>

      <Button onClick={increment} />



      <div>{counter}</div>

    </div>

  );

}



ReactDOM.render(

  <Parent />,

  document.getElementById('root')

);


<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>

<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>



<div id="root"></div>


 类似资料:
  • 我有两个组件,一个组件将一些func作为道具传递给另一个组件,我不确定什么是正确的方法来做到这一点,而不必接收eslint错误: 代码:

  • 问题内容: 我们都知道我们需要在React中绑定函数以使其起作用。我知道为什么我们需要绑定它。 但是我不确定为什么我们不需要绑定箭头功能。 示例:使用箭头功能(无需绑定) }; 现在,使用功能(需要绑定) }; 我不是在问为什么我们需要绑定功能。我只想知道为什么箭头功能不需要绑定。 谢谢。 问题答案: 仅仅因为arrow函数的上下文中没有以下内容: 这个 论点 超 新目标 所以,当你引用此箭头功能

  • 本文向大家介绍使用箭头函数应该需要注意什么?相关面试题,主要包含被问及使用箭头函数应该需要注意什么?时的应答技巧和注意事项,需要的朋友参考一下

  • 问题内容: 我有一个容器,需要更改显示表单或显示成功页面的UI表单。 容器具有state.showSuccess,我需要MyFormModule才能调用容器以更改状态。 下面的代码有效,但出现以下警告: “ JSX道具不应该使用.bind()” 不使用.bind()怎么办? 问题答案: 您应该首先了解 为什么 这是一个不好的做法。 这里的主要原因是返回一个新的函数引用。 每次通话都会发生这种情况,

  • 问题内容: 下面的代码在IE 11中不起作用,它在控制台中引发语法错误 使用二部图进行可视化 此代码导致上述声明中的问题 问题答案: 您正在使用箭头功能。IE11不支持它们。使用函数代替。 这是Babel将其翻译成ES5的内容:

  • 通过和,我们将获得两种非常相似的在ES6中编写函数的方法。在其他语言中,lambda函数通常以匿名的方式区别于其他语言,但在ECMAScript中,任何函数都可以是匿名的。这两种类型都有独特的使用域(即当需要显式绑定或显式不绑定时)。在这两个领域之间,有很多情况下,任何一种表示法都可以。 ES6中的箭头函数至少有两个限制: null null