ant-design / ant-design/x

conversations组件items过多时(超过100),点击切换卡顿

Open
#1,871 1 comment 1 reaction 0 assignees View on GitHub
bug
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.