在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结果。我已经定义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容易出现问题的更多相关文章
- 在react jsx中使用if判断
在react jsx中如果使用if判断,需要这样做 var loginButton; if (loggedIn) { loginButton = <LogoutButton />; } e ...
- js中this,箭头函数和普通函数
四种基本用法 1. 一般方法中,this代指全局对象 window 2. 作为对象方法调用,this代指当前对象 3. 作为构造函数调用,this 指代new 出的对象 function test() ...
- JS中generater和箭头函数
generater跟函数很像: function* fn(x){ yield x; yield x++; return x;} 如上所示,generater用function*定义,可以用yield返 ...
- JS 函数(arguments、箭头函数、bind)
参数 函数内部可用的 arguments 对象来访问函数的实参 注意 在函数递归调用的时候(在某一刻同一个函数运行了多次,也就是有多套实参),那么 arguments 属性的值是最近一次该函数调用时传 ...
- es6中的双箭头函数
原代码: const fetchPosts = subreddit => dispatch => { dispatch(requestPosts(subreddit)); return c ...
- react jsx 中使用 switch case 示例
<div> <span>适用平台:</span> <span>{(() => { switch (currentItems.usePlatform ...
- 普通函数跟箭头函数中this的指向问题
箭头函数和普通函数的区别如下. 普通函数:根据调用我的人(谁调用我,我的this就指向谁) 箭头函数:根据所在的环境(我再哪个环境中,this就指向谁) 一针见血式总结: 普通函数中的this: 1. ...
- => js 中箭头函数使用总结
箭头函数感性认识 箭头函数 是在es6 中添加的一种规范 x => x * x 相当于 function(x){return x*x} 箭头函数相当于 匿名函数, 简化了函数的定义. 语言的发展 ...
- ES6中箭头函数的作用
我们知道在ES6中,引入了箭头函数,其本质就是等同有ES5中的函数.类似于下面的写法: let test1=() => “abc”; let test2=() => { return “a ...
随机推荐
- Codeforces 932 A.Palindromic Supersequence (ICM Technex 2018 and Codeforces Round #463 (Div. 1 + Div. 2, combined))
占坑,明天写,想把D补出来一起写.2/20/2018 11:17:00 PM ----------------------------------------------------------我是分 ...
- 2002-2003 ACM-ICPC Northeastern European Regional Contest (NEERC 02)
B Bricks 计算几何乱搞 题意: 给你个立方体,问你能不能放进一个管道里面. 题解: 这是一道非常迷的题,其问题在于,你可以不正着放下去,你需要斜着放.此时你需要枚举你旋转的角度,来判断是否可行 ...
- BZOJ1014火星人prefix Splay維護序列 + 字符串哈希
@[Splay, 哈希] Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:\(madamimadam\), 我们将这个字符串的各个字符予以标号 ...
- link2005 重复定义错误
造成LNK2005错误主要有以下几种情况: 1.重复定义全局变量. 对于一些初学编程的程序员,有时候会以为需要使用全局变量的地方就可以使用定义申明一下.其实这是错误的,全局变量是针对整个工程的. 正 ...
- pv,uv
1.PV PV(page view),即页面浏览量:用户每1次对网站中的每个网页访问均被记录1次.用户对同一页面的多次访问,访问量累计. 2.什么是UV uv(unique visitor),指访问某 ...
- DELPHI是怎么实现跨平台的?
DELPHI是怎么实现跨平台的? 首先跨平台必须要兼容原来的语法,以线程的临界区对象为例: TCriticalSection = class(TSynchroObject){$IFDEF POSIX} ...
- 【IntelliJ IDEA】在idea上安装使用svn
1.在电脑上安装SVN 下载地址:64位SVN下载 然后一路next,安装完成即可. 如果忘记勾选第二个,可以重新点击安装包 重新安装,然后选择modify,然后勾选command line cli ...
- 3D投影
3D投影方式的几大种类: 1.快门式 主动快门式即时分式,不过我们通常用前面的叫法,快门式3D眼镜(3D Shutter Glasses,也称作LC shutter glassesor active ...
- cucumber 使用资料
1.cucumber reporting github:https://github.com/damianszczepanik/cucumber-reporting 配置:详细参考上述地址描述 a.添 ...
- vue2.0 自定义 饼状图 (Echarts)组件
1.自定义 图表 组件 Echarts.vue <!-- 自定义 echart 组件 --> <template> <div> <!-- echart表格 ...