javascript - 对从子组件更改父组件状态而不重新渲染所有子组件的最佳实践做出反应?
问题描述
我有一个项目,我在其中显示包含文本字段中人员属性的卡片,用户可以编辑文本字段以直接更改该人的属性值。但是,每次他们编辑文本字段时,都会重新渲染所有卡片,从而减慢应用程序的速度。这是一个例子:
export default Parent() {
const [personList, setPersonList] = useState(/* list of person objects*/);
const modifyPerson(index, property, value) {
const newPersonList = _.cloneDeep(personList);
newPersonList[index][property] = value;
setPersonList(newPersonList);
}
const children = personList.map((person, index) => {
<Person
modifyPerson={modifyPerson}
index=index
/*properties on the person */
/>
});
return <div> {children} </div>
}
export default Person(props) {
const fields = /* assume a list of these textfields for each property */
<TextField
value={props.name}
onChange={(e) => modifyPerson(props.index,"name",e.target.value)}
value={props.name} >
return {fields};
}
因此,本质上,当子项的文本字段更新时,它会触发存储新值的父项中的状态更改,然后刷新子项的外观。用户没有点击按钮来“保存”这些值——一旦他们编辑了文本字段,它就是一个永久性的改变。而且父级需要知道每个 Person 的新值,因为有些功能需要知道人员列表的当前状态。Person 组件包含的图像如果处理效率低下会减慢渲染速度。
有没有更好的方法让这个设计更高效并减少重新渲染?我尝试使用 useCallback 来保留函数,但它在这个特定设计中不起作用,因为属性和值不同——我是否必须为每个确切的属性创建一个新的“modifyPerson”?
解决方案
正如其他人已经说过React.memo()
的那样,这是去这里的方式,但这仍然会重新渲染,因为您modifyPerson
每次都重新创建。您可以使用useCallback
来始终获得相同的函数标识,但是对于您当前的实现,您必须添加personList
为依赖项,这样也不起作用。
有一个技巧setPersonList
,它还接受一个接受当前状态并返回下一个状态的函数。这种方式modifyPerson
不依赖于任何外部范围(期望setPersonList
通过反应保证始终具有相同的身份)并且只需要创建一次。
const modifyPerson = useCallback((index, property, value) {
setPersonList(currentPersonList => {
const newPersonList = _.cloneDeep(currentPersonList);
newPersonList[index][property] = value;
return newPersonList;
})
}, []);
推荐阅读
- javascript - 仅当值未定义时才显示 Angular 的工具提示(ng2-tooltip-directive)
- drupal-7 - Solr Search_api_attachment 从 drush 索引时失败
- python - 在python plotly dash散点图中取消全选
- javascript - 在javascript中计算工作时间的差异
- asp.net-core - 如何等待从 Redis 订阅的消息?
- c# - 如何在 C# 中使用逐字字符串?
- asp.net-core-2.1 - Microsoft.AspNetCore.Mvc.ActionResult
返回额外的常用信息 - c++ - 调用从模板派生的类的静态方法而不指定模板
- python - 用excel写一个矩阵
- python-3.x - 如何使用 pytest monkeypatch 模拟两个连续的控制台输入