• 在react jsx中,为什么使用箭头函数和bind容易出现问题


    在之前的文章中,已经说明如何避免在react jsx中使用箭头函数和bind(https://medium.freecodecamp.o... 但是没有提供一个清晰的demo展示为什么要这样做。

    现在来一些例子吧。

    在这个例子中,我们通过使用一个箭头函数(=>)来bind用户ID到每个删除按钮中。

    
    ## index.js 
    
    import React from 'react';
    import { render } from 'react-dom';
    import User from './User';
    
    class App extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          users: [
            { id: 1, name: 'Cory' }, 
            { id: 2, name: 'Meg' }, 
            { id: 3, name: 'Bob' }
          ]
        };
      }
      
      deleteUser = id => {
        this.setState(prevState => {
          return { 
            users: prevState.users.filter( user => user.id !== id)
          }
        })
      }
    
      render() {
        return (
          <div>
            <h1>Users</h1>
            <ul>
            { 
              this.state.users.map( user => {
                return <User 
                  key={user.id} 
                  name={user.name} 
                  onDeleteClick={() => this.deleteUser(user.id)} />
              })
            }
            </ul>
          </div>
        );
      }
    }
    
    export default App;
    
    render(<App />, document.getElementById('root'));
    
    

    onDeleteClick={() => this.deleteUser(user.id)}这一行中,我们使用一个箭头函数来传递value到deleteUser 函数中。这就是问题所在了。

    
    ## User.js
    
    import React from 'react';
    
    // Note how the debugger below gets hit when *any* delete
    // button is clicked. Why? Because the parent component
    // uses an arrow function, which means this component
    //
    class User extends React.PureComponent {
      render() {
        const {name, onDeleteClick } = this.props
        console.log(`${name} just rendered`);
        return (
          <li>             
            <input 
              type="button" 
              value="Delete" 
              onClick={onDeleteClick} 
            /> 
            {name}
          </li>
        );
      }
    }
    
    export default User;
    
    

    看一看User.js文件。每当我登录的时候控制台都会打印出渲染执行时的console结果。我已经定义UserPureComponent。所以只有当props或者state修改时才会重新渲染User。但是当你点击删除的时候,发现render在所有User实例中触发了。

    怎么会这个样子?因为()=>this.deleteUser(user.id)每执行一次就会生成一个新的函数,当然bind也是这样干的,所以在PureComponent的shallowCompare中认为onDeleteClick的值已经被修改,所以触发了重新渲染。看吧,使用箭头函数和bind会造成性能浪费,作为一个节约的程序员应该避免如此。

    那我们应该怎样做呢?

    请看下面的代码

    
    import React from 'react';
    import { render } from 'react-dom';
    import User from './User';
    
    class App extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          users: [
            { id: 1, name: 'Cory' }, 
            { id: 2, name: 'Meg' }, 
            { id: 3, name: 'Bob'}
          ],
        };
      }
    
      deleteUser = id => {
        this.setState(prevState => {
          return { 
            users: prevState.users.filter(user => user.id !== id) 
          };
        });
      };
    
      renderUser = user => {
        return <User key={user.id} user={user} onClick={this.deleteUser} />;
      }
    
      render() {
        return (
          <div>
            <h1>Users</h1>
            <ul>
              {this.state.users.map(this.renderUser)}
            </ul>
          </div>
        );
      }
    }
    
    render(<App />, document.getElementById('root'));
    
    

    上面的例子就没有箭头函数了。这里面使用了闭包的概念,把user传递下去了。

    来源:https://segmentfault.com/a/1190000011007769

  • 相关阅读:
    MT【38】与砝码有关的两个题
    MT【37】二次函数与整系数有关的题
    MT【36】反函数有关的一道题
    MT【35】用复数得到的两组恒等式
    MT【34】正余弦的正整数幂次快速表示成正余弦的线性组合
    MT【33】证明琴生不等式
    MT【32】内外圆(Apollonius Circle)的几何证明
    MT【31】傅里叶级数为背景的三角求和
    MT【30】椭圆的第二定义解题
    MT【29】介绍向量的外积及应用举例
  • 原文地址:https://www.cnblogs.com/qixidi/p/10160748.html
Copyright © 2020-2023  润新知