perf(console): 日志行加 memo —— 点折叠卡死就是这个
日志是「来一条 push 一条」,store 里的数组每来一条就是新的,于是整个列表重渲染; 而列表最多留 500 条,不做 memo 就是每来一行重渲染 500 行,每行还要跑 5 次 cn() (tailwind-merge 不便宜)。爬虫一跑日志是成片来的,主线程直接被占满 —— 表现就是 点什么都没反应,点折叠最容易注意到,因为那一下还要把整份列表挂载/卸载一遍。 log 对象在数组里是稳定引用,memo 之后只有新来的那一行会渲染。
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
import { memo } from 'react'
|
||||||
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import type { LogEntry } from '@/types/crawler'
|
import type { LogEntry } from '@/types/crawler'
|
||||||
|
|
||||||
@@ -41,7 +43,18 @@ const levelIcons: Record<string, string> = {
|
|||||||
debug: 'DBG',
|
debug: 'DBG',
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TerminalLine({ log }: TerminalLineProps) {
|
/**
|
||||||
|
* 一行日志。
|
||||||
|
*
|
||||||
|
* **必须 memo。** 日志是「来一条就 push 一条」,每来一条 store 里的数组就是新的,
|
||||||
|
* 于是整个列表重渲染;而这个列表最多留 500 条 —— 不做 memo 就是每来一行重渲染 500 行,
|
||||||
|
* 每行还要跑 5 次 `cn()`(tailwind-merge 不便宜)。爬虫在跑的时候日志是成片来的,
|
||||||
|
* 主线程直接被占满,表现就是**点什么都没反应**(点折叠最容易注意到,因为那一下还要
|
||||||
|
* 把整份列表挂载/卸载一遍)。
|
||||||
|
*
|
||||||
|
* `log` 对象在数组里是稳定引用,所以 memo 之后只有新来的那一行会渲染。
|
||||||
|
*/
|
||||||
|
export const TerminalLine = memo(function TerminalLine({ log }: TerminalLineProps) {
|
||||||
const config = levelConfig[log.level] || levelConfig.info
|
const config = levelConfig[log.level] || levelConfig.info
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -67,4 +80,4 @@ export function TerminalLine({ log }: TerminalLineProps) {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user