conversations组件items过多时(超过100),点击切换卡顿
- Dominant language
- TypeScript
- Stars
- 4.8k
- Forks
- 1.2k
- Avg merge
- 3d 3h
- Merged PRs (30d)
- 2
Description
### 重现步骤
示例代码:
'use client'
import { useState, useCallback, useMemo } from 'react'
import { Conversations, type ConversationItemType } from '@ant-design/x'
import { MessageOutlined, UserOutlined, DeleteOutlined, EditOutlined } from '@ant-design/icons'
import { Modal, Input, message, Button } from 'antd'
import type { MenuProps } from 'antd'
const generateMockData = (start: number, count: number): ConversationItemType[] => {
const now = Date.now()
const day = 24 * 60 * 60 * 1000
const items: ConversationItemType[] = []
for (let i = start; i < start + count; i++) {
const isToday = i <= 150
const isYesterday = i > 150 && i <= 300
items.push({
key: String(i),
label: `会话 ${i}`,
timestamp: isToday
? now - (i - 1) * 3600000
: isYesterday
? now - day - (i - 151) * 3600000
: now - (2 * day) - (i - 301) * 3600000,
group: isToday ? '今天' : isYesterday ? '昨天' : '更早',
icon: i % 3 === 0 ? : ,
})
}
return items
}
const PAGE_SIZE = 50
export default function Home() {
const [items, setItems] = useState(() => generateMockData(1, PAGE_SIZE))
const [activeKey, setActiveKey] = useState('1')
const [renameValue, setRenameValue] = useState('')
const [isModalOpen, setIsModalOpen] = useState(false)
const [loading, setLoading] = useState(false)
const [hasMore, setHasMore] = useState(true)
const loadMore = useCallback(async () => {
setLoading(true)
await new Promise((r) => setTimeout(r, 300))
const nextItems = generateMockData(items.length + 1, PAGE_SIZE)
if (nextItems.length > 0) {
setItems((prev) => [...prev, ...nextItems])
if (items.length >= 500) {
setHasMore(false)
}
} else {
setHasMore(false)
}
setLoading(false)
}, [items.length])
const handleMenuClick: MenuProps['onClick'] = ({ key }) => {
if (!activeKey) return
if (key === 'delete') {
setItems((prev) => prev.filter((item) => item.key !== activeKey))
message.success('删除成功')
} else if (key === 'rename') {
setRenameValue(
items.find((item) => item.key === activeKey)?.label?.toString() || ''
)
setIsModalOpen(true)
}
}
const menuItems: MenuProps['items'] = useMemo(() => [
{
key: 'rename',
icon: ,
label: '重命名',
},
{
key: 'delete',
icon: ,
label: '删除',
danger: true,
},
], [])
const handleRenameOk = () => {
if (activeKey && renameValue.trim()) {
setItems((prev) =>
prev.map((item) =>
item.key === activeKey ? { ...item, label: renameValue.trim() } : item
)
)
message.success('重命名成功')
setIsModalOpen(false)
}
}
return (
{hasMore && (
加载更多 ({items.length}/500)
)}
setIsModalOpen(false)}
>
setRenameValue(e.target.value)}
placeholder="请输入新名称"
/>
)
}
### 当前行为
当item数量过大时,比如500,界面切换item有卡顿感,打开f12 console中日志:[Violation] 'click' handler took ms
[Violation] 'click' handler took 169ms
react-dom.development.js:8016 [Violation] 'click' handler took 195ms
react-dom.development.js:8016 [Violation] 'click' handler took 215ms
react-dom.development.js:8016 [Violation] 'click' handler took 244ms
react-dom.development.js:8016 [Violation] 'click' handler took 270ms
react-dom.development.js:8016 [Violation] 'click' handler took 274ms
react-dom.development.js:8016 [Violation] 'click' handler took 268ms
react-dom.development.js:8016 [Violation] 'click' handler took 264ms
react-dom.development.js:8016 [Violation] 'click' handler took 262ms
### 预期行为
_No response_
### 上下文
_No response_
### 版本
2.5.0
### 您在哪些浏览器上遇到了这个问题?
Chrome
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the provided Conversations reproduction in Chrome and profile item switching with around 500 items, focusing on the Conversations component entry point and the reported click-handler violations. Trace the render and update work triggered by changing the active item, then define completion as responsive switching at large item counts with coverage for the regression.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- frontend, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100