我正在寻找React组件中箭头函数的优雅替代品。
Apparently in React,在父容器中使用箭头函数会导致儿童的性能问题。这是因为匿名箭头函数被认为是“新”函数实例,因此每个父级render()
都会导致纯组件重新渲染(如果所述箭头函数向下传递)。
我个人喜欢箭头功能的使用以提高可读性。以下面的代码为例:
render() {
return (
<div>
<h1>Users</h1>
<ul>
{this.state.users.map(user => {
return (
<User key={user.id} user={user} onClick={(e) => this.deleteUser(e, user.id)} />;
)
}}
</ul>
</div>
);
}
很明显this.deleteUser()
从哪里得到它的论据。但将其与“应该完成”的方式进行比较:
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'));
为什么??这是不太可读的。你怎么知道this.renderUser
得到user
作为参数传递?你怎么知道this.deleteUser
得到userId
作为参数传递?
有什么替代品?现有的stackoverflow question建议将孩子们移动到他们自己的组件中并通过道具传递参数,但有时你不希望变得如此模块化。
没有像箭头功能那样优雅的理智解决方案吗?或者,我们最好的希望是等到React团队为了可读性和社区采用而修补此问题?
你怎么知道this.renderUser让用户作为参数传入?你怎么知道this.deleteUser获取userId作为参数传入?
我们以this.state.users.map(this.renderUser)
为例。如你所知,你的this.state.users
是一个数组。这表明map
是Array.map函数。函数签名看起来像这样(以简化形式)
someArray.map(currentItem => {
// Handle your item here
});
如你所见,它需要回调。该回调本身最多可以包含3个参数(我们这里只需要一个)。现在回头看看你的this.renderUser
我们可以看到它也是一个带有一个参数的函数。
然后我们可以将它用作我们之前的map
函数的回调。如果我们只是复制/粘贴它的实现,我们会有这样的东西
this.state.users.map(user => {
return <User key={user.id} user={user} onClick={this.deleteUser} />;
});
所以当你写this.state.users.map(this.renderUser)
时,你做的就像复制/粘贴你的功能一样。在两种情况下,user
论证都是相同的
在研究了更多之后,我正在寻找的折衷可以通过返回函数的JS函数来实现。
由此:
<div onClick={(e) => this.doSomething(e, 'abc')}></div>
对此:
doSomething = (param) => (e) => {
console.log(param) // 'abc'
console.log(e.target.value) // 'hello world'
}
<input onChange={this.doSomething('abc')}></div>
在我看来,仍然不像<input onChange={(e) => this.doSomething(e, 'abc')}></div>
那样优雅和可读,但效果还不错。