本文是以下文章的总结
问题引入
components/User.jsx
import React from "react";
class User extends React.PureComponent {
render() {
const { name, onDeleteClick, id } = this.props;
console.log(`${name} just rendered`);
return (
<li>
<input type="button" value="Delete" onClick={onDeleteClick} />
{name}
</li>
);
}
}
export default User;
App.jsx
import React from "react";
import User from "./components/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}
id={user.id}
onDeleteClick={() => this.deleteUser(user.id)}
/>
);
})}
</ul>
</div>
);
}
}
export default App;
当state
或者props
发生变化时, React会执行组件的render
方法.
用户点击删除按钮之后触发以下流程:
- 触发
onDeleteClick
事件 - 执行
() => this.deleteUser(id)
setState
方法修改users
状态- 状态发生变化, 触发
<App >
组件的render
方法 <App />
组件的render
方法会传递新的一个箭头函数给<User />
组件的onDeleteClick
属性- 导致
<User />
的props发生变化, 重新执行<User />
组件的render
方法
原因就是箭头函数每次都是新的, 导致<App />
组件每次执行render
发放时, <User />
的props
都会发生变化.
解决方案
文章开始引用的博文里给的解决方案是<User />
组件内部调用 onDeleteClick
方法时把id传过去:
components/User.jsx
<input value="Delete" onClick={() => this.onDeleteClick(this.props.id)} />
App.jsx
<User key={user.id} name={user.name} id={user.id} onDeleteClick={this.deleteUser} />
但是这个方案有个缺陷, 就是子组件需要关心入参, 而且那个入参可能是子组件不知道的.
为了解决这个问题, 可以给state上的每个user数据添加一个delete函数:
App.jsx
class App extends React.Component {
constructor() {
// ...
this.state.users.forEach(item => {
item.onDelete = () => {
this.deleteUser(item.id);
}
});
// ...
}
render() {
// ...
<User
key={user.id}
name={user.name}
id={user.id}
onDeleteClick={user.onDelete}
/>
// ...
}
}