React 动态生成下拉复选框列表(含全选切换)点击延迟问题求助
性能瓶颈核心原因
当前代码的性能问题主要来自高频O(n)遍历、大量无意义重复渲染,以及内部状态冗余三个方面,优化点如下:
1. 替换数组查找为O(1)复杂度的Set查询
当前每个复选框的选中状态判断用selections.includes(option.id),当选项数量较多时,每次渲染所有选项都会触发n次数组遍历,全选操作时遍历成本会成倍增长。可以通过useMemo缓存选中项的Set结构,将查找复杂度从O(n)降到O(1):
// 在FilterInterface组件内新增 const selectedSet = React.useMemo(() => new Set(selections), [selections]) // 复选框checked属性改为 checked={selectedSet.has(option.id)}
2. 记忆化列表项避免全量重渲染
将每个复选框选项抽为独立组件,用React.memo包裹,只有当前选项的选中状态、回调函数变化时才会重渲染,避免每次选中状态变更所有选项都跟着重绘:
const FilterOption = React.memo(({ option, isSelected, onCheck }) => { return ( <DropdownItem header key={option.id} value={option.name} className="filterCheckbox" > <Label onClick={() => onCheck(option.id)}> <Checkbox checked={isSelected} readOnly /> <span>{option.name}</span> </Label> </DropdownItem> ) }) // FilterInterface内渲染列表改为 {options?.map(option => ( <FilterOption key={option.id} option={option} isSelected={selectedSet.has(option.id)} onCheck={handleCheck} /> ))}
3. 移除冗余内部状态,用计算值代替allSelected
当前在FilterInterface内单独维护allSelected状态,不仅容易和外部传入的selections不同步,还会触发额外的组件重渲染。改为用useMemo直接计算全选状态即可:
// 移除原来的allSelected state,新增 const allSelected = React.useMemo(() => { return options.length > 0 && selections.length === options.length }, [selections.length, options.length])
4. 用useCallback缓存内部回调函数
当前FilterInterface内的toggleAllSelected、handleCheck每次组件渲染都会生成新的实例,会导致记忆化的子组件失效,需要用useCallback包裹:
const toggleAllSelected = React.useCallback(() => { if (!allSelected) { const newSelections = options.map(option => option.id) handler(newSelections) } else { handler([]) } }, [allSelected, options, handler]) const handleCheck = React.useCallback(id => { let newArray if (selectedSet.has(id)) { newArray = selections.filter(selection => selection !== id) } else { newArray = [...selections, id] } handler(newArray) }, [selectedSet, selections, handler])
5. 超大选项量场景新增虚拟滚动
如果你的筛选选项数量超过100条,建议接入虚拟滚动库只渲染可视区域内的选项,无论总选项数多少,实际渲染节点数都控制在20以内,性能会有量级提升。
内容的提问来源于stack exchange,提问作者Andrew Lentz
相关产品推荐
相关产品推荐

