如何避免在渲染方法中绑定或内联箭头函数 [英] How to avoid bind or inline arrow functions inside render method

查看:24
本文介绍了如何避免在渲染方法中绑定或内联箭头函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们应该避免在 render 内部绑定方法,因为在重新渲染时它会创建新方法而不是使用旧方法,这会影响性能.

对于这样的场景:

我们可以在构造函数中绑定_handleChange方法:

this._handleChange = this._handleChange.bind(this);

或者我们可以使用属性初始化语法:

_handleChange = () =>{....}

现在让我们考虑我们想要传递一些额外参数的情况,假设在一个简单的待办事项应用程序中,点击项目我需要从数组中删除项目,为此我需要传递项目索引或待办事项每个 onClick 方法中的名称:

todos.map(el => 

{el}

)

现在假设 todo 名称是唯一的.

根据DOC:

<块引用>

这种语法的问题是创建了不同的回调每次组件渲染时.

问题:

如何在render方法中避免这种绑定方式或者有什么替代方法?

请提供任何参考或示例,谢谢.

解决方案

首先: 一个简单的解决方案是为 map 函数内的内容创建一个组件,并将值作为 props 和何时传递您从子组件调用函数,您可以将值传递给作为道具传递的函数.

父母

deleteTodo = (val) =>{控制台日志(val)}todos.map(el =><MyComponent val={el} onClick={this.deleteTodo}/>)

我的组件

class MyComponent 扩展 React.Component {deleteTodo = () =>{this.props.onClick(this.props.val);}使成为() {return 

{this.props.val} </div>}}

示例代码段

class Parent extends React.Component {_deleteTodo = (val) =>{控制台日志(val)}使成为() {var todos = ['a', 'b', 'c'];返回 (<div>{todos.map(el =><MyComponent key={el} val={el} onClick={this._deleteTodo}/>)}

)}}class MyComponent 扩展了 React.Component {_deleteTodo = () =>{console.log('这里');this.props.onClick(this.props.val);}使成为() {return

{this.props.val} </div>}}ReactDOM.render(, document.getElementById('app'));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script><div id="app"></div>

第二:另一种方法是使用 memoize 并返回一个函数

constructor() {极好的();this._deleteTodoListener = _.memoize(this._deleteTodo, (元素) =>{返回 element.hashCode();})}_deleteTodo = (元素) =>{//这里删除处理}

并像使用它一样

todos.map(el => 

{el}

)

<块引用>

附言然而,这不是最好的解决方案,仍然会导致正在创建多个功能,但仍然比初始案例.

第三:然而,更合适的解决方案是将 attribute 添加到最顶层的 div 并从 event 中获取值,例如

_deleteTodo = (e) =>{console.log(e.currentTarget.getAttribute('data-value'));}todos.map(el => <div key={el} data-value={el} onClick={this._deleteTodo}> {el} </div>)

但是,在这种情况下,使用 toString 方法将属性转换为字符串,因此对象将转换为 [Object Object] 和数组,如 ["1" , "2", "3"]"1, 2, 3"

We should avoid method binding inside render because during re-rendering it will create the new methods instead of using the old one, that will affect the performance.

So for the scenarios like this:

<input onChange = { this._handleChange.bind(this) } ...../>

We can bind _handleChange method either in constructor:

this._handleChange = this._handleChange.bind(this);

Or we can use property initializer syntax:

_handleChange = () => {....}

Now lets consider the case where we want to pass some extra parameter, lets say in a simple todo app, onclick of item i need to delete the item from array, for that i need to pass either the item index or the todo name in each onClick method:

todos.map(el => <div key={el} onClick={this._deleteTodo.bind(this, el)}> {el} </div>)

For now just assume that todo names are unique.

As per DOC:

The problem with this syntax is that a different callback is created each time the component renders.

Question:

How to avoid this way of binding inside render method or what are the alternatives of this?

Kindly provide any reference or example, thanks.

解决方案

First: A simple solution will be to create a component for the content inside a map function and pass the values as props and when you call the function from the child component you can pass the value to the function passed down as props.

Parent

deleteTodo = (val) => {
    console.log(val)
}
todos.map(el => 
    <MyComponent val={el} onClick={this.deleteTodo}/> 

)

MyComponent

class MyComponent extends React.Component {
    deleteTodo = () => {
        this.props.onClick(this.props.val);
    }
    render() {
       return <div  onClick={this.deleteTodo}> {this.props.val} </div>
    }
}

Sample snippet

class Parent extends React.Component {
     _deleteTodo = (val) => {
        console.log(val)
    }
    render() {
        var todos = ['a', 'b', 'c'];
        return (
           <div>{todos.map(el => 
             <MyComponent key={el} val={el} onClick={this._deleteTodo}/> 
        
           )}</div>
        )
    }
    
   
}

class MyComponent extends React.Component {
        _deleteTodo = () => {
                     console.log('here');   this.props.onClick(this.props.val);
        }
        render() {
           return <div onClick={this._deleteTodo}> {this.props.val} </div>
        }
    }
    
ReactDOM.render(<Parent/>, document.getElementById('app'));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

EDIT:

Second: The other approach to it would be to use memoize and return a function

constructor() {
    super();
    this._deleteTodoListener = _.memoize(
                   this._deleteTodo, (element) => {
                        return element.hashCode();
                    }
              )
}

_deleteTodo = (element) => {
   //delete handling here
}

and using it like

todos.map(el => <div key={el} onClick={this._deleteTodoListener(el)}> {el} </div>)

P.S. However this is not a best solution and will still result in multiple functions being created but is still an improvement over the initial case.

Third: However a more appropriate solution to this will be to add an attribute to the topmost div and get the value from event like

_deleteTodo = (e) => {
     console.log(e.currentTarget.getAttribute('data-value'));

 }

 todos.map(el => <div key={el} data-value={el} onClick={this._deleteTodo}> {el} </div>)

However, in this case the attributes are converted to string using toString method and hence and object will be converted to [Object Object] and and array like ["1" , "2", "3"] as "1, 2, 3"

这篇关于如何避免在渲染方法中绑定或内联箭头函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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