1. 程式人生 > >在react jsx中,為什麽使用箭頭函數和bind容易出現問題

在react jsx中,為什麽使用箭頭函數和bind容易出現問題

https bind users uri ops segment why note 發現

在之前的文章中,已經說明如何避免在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結果。我已經定義User為PureComponent。所以只有當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

在react jsx中,為什麽使用箭頭函數和bind容易出現問題