微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在不重新渲染所有子项的情况下,响应从子项更改父组件状态的最佳实践?

如何解决在不重新渲染所有子项的情况下,响应从子项更改父组件状态的最佳实践?

我有一个项目,我在文本字段中显示包含某人属性的卡片,用户可以编辑文本字段以直接更改该人的属性值。但是,每次他们编辑文本字段时,都会导致重新渲染所有卡片,从而降低应用程序的速度。下面是一个例子:

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()

React.Memo 将检查传递给组件的 props,只有当 props 发生变化时,它才会重新渲染该特定组件。

因此,如果您有多个 Person 组件正在获取这些 Person 明确的道具,并且当您更改导致父状态更新的特定 Person 组件时,只有您修改过的 Person 组件会重新渲染,因为它的 props 会发生变化(假设您将更改的值传递给它)。

其他组件将拥有相同的道具并且不会改变。

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() 是这里的方法,但这仍然会重新渲染,因为您每次都重新创建 modifyPerson。您可以使用 useCallback 来始终获得相同的函数标识,但是对于您当前的实现,您必须将 personList 添加为依赖项,因此这也不起作用。

setPersonList 有一个技巧,它也接受一个函数,该函数接受当前状态并返回下一个状态。这样 modifyPerson 不依赖于任何外部作用域(期望 setPersonList 通过反应保证始终具有相同的标识)并且只需要创建一次。

const modifyPerson = useCallback((index,property,value) {
    setPersonList(currentPersonList => {
        const newPersonList = _.cloneDeep(currentPersonList);
        newPersonList[index][property] = value;
        return newPersonList;
    })
},[]);

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。