【问题标题】:Stop entire List from rerendering on selecting element阻止整个列表在选择元素时重新呈现
【发布时间】:2022-11-07 22:31:59
【问题描述】:

我正在努力阻止我的整个列表重新渲染。当我选择一个项目时,它应该加下划线。如果重新渲染新选择的元素和先前选择的元素就足够了。
在最坏的情况下,这个 List 可以包含数百个条目,而且速度非常慢。所以我尝试使用 React.memo 方法,但我可能用错了。
这是我的 List 和 ListEntry 的自定义函数(更改选定当前选择是父级的 state 和 setState 函数)

function CustomList(props: any) {
    return (
            <List
                component="div"
            >
                {props.data.map((entryData: any, index: number) => {
                    return (
                        <React.Fragment key={index}>
                            <CustomListEntry
                                entryData={entryData}
                                changeSelected={props.changeSelected}
                                style={{
                                    borderBottom:
                                        props.currentlySelected == entryData.id ? "dashed" : "",
                                }}
                            />
                        </React.Fragment>
                    );
                })}
            </List>
        
    );
}
const CustomListEntry = React.memo((props: any) => {
    return (
        <ListItemButton
            style={props.style}
            onClick={() => {
                props.changeSelected(props.entryData.id);
            }}
        >
            <ListItemText>
                    {props.entryData.exampledata}
            </ListItemText>
        </ListItemButton>
    );
});

和父组件:

function Root(props:any){
const [selectedId, setSelectedId] = React.useState("");
   ...
    return{
                <CustomList
                    data={data}
                    changeSelected={setSelectedId}
                    currentlySelected={selectedId}
                ></CustomList>
    }
}

【问题讨论】:

  • 这也取决于您的更新功能changeSelected,您也可以分享那部分吗?我们可以帮助您检查
  • 我添加了父组件,但它实际上只是正常反应状态的传递

标签: reactjs


【解决方案1】:

原因很简单:当你改变父级的状态时,父级会重新渲染,强制所有子元素重新渲染。

请注意,无论如何这都不应该太长,因此您可能在某处遇到另一个性能问题:)(DOM 不会通过反应更新)-例如在某处有 console.log(..)

这是一个代码笔,列表中有 10k 个按钮,但您仍然可以看到渲染非常快:https://codepen.io/aSH-uncover/pen/rNKWaKE

for (let i = 0 ; i < 10000 ; i++) {
  data.push({ id: String(i), exampledata: `Value ${i}`})
}

如果您真的需要摆脱整个渲染,您将不得不采取另一种方法,例如每个按钮一个条目的全局存储,并停止将 selectedId 存储在父状态:)

【讨论】:

    猜你喜欢
    • 2023-03-11
    • 2014-06-20
    • 2021-12-05
    • 1970-01-01
    • 1970-01-01
    • 2021-06-08
    • 1970-01-01
    • 2023-01-13
    • 1970-01-01
    相关资源
    最近更新 更多