如何解决React Material UI防止列表重新呈现
当我点击展开图标时,我将面临列表中不必要的重新渲染。 目前,我可以在Profiler中看到整个列表都已重新呈现,并且当我尝试将列表包装在React备忘录中时,它不能解决问题。 我有什么办法可以阻止整个列表的重新呈现?
目标是使用navigation
变量构建模块化的侧面菜单。
const navigation = [
{ id: "Überschrift",type: "header" },{ id: "Test",icon: <StarBorder />,type: "category" },{
id: "Navigation 1",icon: <AcUnitIcon />,type: "category",children: [
{ id: "Sent mail",icon: <InboxIcon />,active: true },{ id: "Drafts",icon: <DraftsIcon /> },{ id: "Inbox",icon: <SendIcon /> }
]
},];
问题是,如果一个孩子处于活动状态,则触发父列表的折叠。
我编写了updateparent
函数。
const updateparent = (childId,id) => {
console.log("updateparent");
if (childId !== openchild) {
console.log("setstate");
setOpenChild(childId);
setOpen((open) => ({ ...open,...{ [id]: true } }));
}
return true;
};
到目前为止,这项工作还可以,但是我的问题是这是否是解决此问题的“官方”方式。
基本上,当map函数遍历所有子级时,我需要使用第二个状态(openchild
)存储最后一个活动项。
如果我不执行此操作,那么我将遇到连续不断的渲染问题。
对于函数调用,我也有一个奇怪的行为:
<ListItem selected={ active === true ? updateparent(childId,id) : false }
updateparent函数呈现两次(从控制台日志中)。谁能解释我为什么会这样?
请查看以下沙箱:
请在下面找到该组件的简化逻辑(我删除了不必要的内容,以解决整个示例在沙箱中运行的问题)
export default function NestedList() {
const [open,setOpen] = React.useState({});
const [openchild,setOpenChild] = React.useState({});
const handleClick = (name) => {
setOpen((open) => ({ ...open,...{ [name]: !open[name] } }));
};
return (
<List component="nav" className={classes.root}>
{navigation.map(({ id,type,icon,active,children }) => {
if (typeof children !== "undefined" && children.length > 0) {
return (
<React.Fragment key={id}>
<ListItem button key={id} onClick={() => handleClick(id)}>
{open[id] ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse in={open[id]} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
{children.map(({ id: childId,active }) => (
<ListItem
selected={
active === true ? updateparent(childId,id) : false
}
>
</ListItem>
))}
</List>
</Collapse>
</React.Fragment>
);
}
)}
</List>
);
}
解决方法
我不确定该解决方案是否是最佳实践,但我可以通过将forceUpdate
函数从父元素传递给子元素来实现。最简单的方法是编写可重用的钩子useForceUpdate
:
function useForceUpdate() {
const [count,setCount] = useState(0);
return () => setCount(val => val + 1);
}
然后像这样在父组件中使用此钩子:
const forceUpdate = useForceUpdate();
在任何子组件中调用forceUpdate
将触发父组件的状态更改,从而迫使父组件重新渲染。确保将此调用包装在条件挂钩或useEffect
挂钩中,以免触发无限的重新渲染循环。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。