[英]React best practice for changing state of parent component from child without rerendering all children?
我有一个项目,我在其中显示包含文本字段中人员属性的卡片,用户可以编辑文本字段以直接更改该人的属性值。 但是,每次他们编辑文本字段时,都会重新渲染所有卡片,从而减慢应用程序的速度。 这是一个例子:
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};
}
所以本质上,当孩子的文本字段被更新时,它会在存储新值的父项中触发 state 更改,然后刷新孩子的样子。 用户没有点击按钮来“保存”这些值——一旦他们编辑了文本字段,它就是一个永久性的改变。 并且父级需要知道每个 Person 的新值,因为有些功能需要知道人员列表的当前 state。 Person 组件包含的图像如果处理效率低下会减慢渲染速度。
有没有更好的方法让这个设计更高效并减少重新渲染? 我试图使用 useCallback 来保留这些功能,但我在这个特定的设计中不起作用,因为属性和值不同——我是否必须为每个确切的属性创建一个新的“modifyPerson”?
React.Memo 将检查传递给组件的 props,只有当 props 发生变化时,它才会重新渲染该特定组件。
因此,如果您有多个Person
组件正在获取对这些Person
明确的道具,并且当您更改导致 Parent state 更新的特定Person
组件时,只有您修改过的Person
组件将重新渲染,因为它的道具将改变(假设您将更改后的值传递给它)。
其他组件将具有相同的道具并且不会改变。
export default React.memo(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};
})
正如其他人已经说过React.memo()
是 go 的方式,但这仍然会重新渲染,因为您每次都重新创建modifyPerson
。 您可以使用useCallback
始终获得与 function 相同的标识,但是对于您当前的实现,您必须将personList
添加为依赖项,这样也不起作用。
setPersonList
有一个技巧,它还接受一个 function,它采用当前的 state 并返回下一个 state。 这样modifyPerson
不依赖于任何外部 scope (期望setPersonList
通过反应保证始终具有相同的身份)并且只需要创建一次。
const modifyPerson = useCallback((index, property, value) {
setPersonList(currentPersonList => {
const newPersonList = _.cloneDeep(currentPersonList);
newPersonList[index][property] = value;
return newPersonList;
})
}, []);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.