在之前的文章中,已经说明如何避免在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: '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传递下去了。