diff --git a/packages/web/src/components/dashboard/top-users-list.tsx b/packages/web/src/components/dashboard/top-users-list.tsx index 79f84ee7..86978e6f 100644 --- a/packages/web/src/components/dashboard/top-users-list.tsx +++ b/packages/web/src/components/dashboard/top-users-list.tsx @@ -1,31 +1,34 @@ -'use client' +"use client"; -import { formatTokens, formatCost } from '@/lib/format' -import type { UserStat } from '@argos/shared' +import { useMemo } from "react"; +import { formatTokens, formatCost } from "@/lib/format"; +import type { UserStat } from "@argos/shared"; interface TopUsersListProps { - users: UserStat[] + users: UserStat[]; } export function TopUsersList({ users }: TopUsersListProps) { + // Use useMemo for expensive synchronous data derivations over lists to avoid recalculation on re-renders + const maxTokens = useMemo( + () => + users.reduce((m, u) => Math.max(m, u.inputTokens + u.outputTokens), 0), + [users], + ); + if (users.length === 0) { return (

최근 7일간 활동한 사용자가 없습니다

- ) + ); } - const maxTokens = users.reduce( - (m, u) => Math.max(m, u.inputTokens + u.outputTokens), - 0, - ) - return (
    {users.map((u, i) => { - const total = u.inputTokens + u.outputTokens - const pct = maxTokens > 0 ? (total / maxTokens) * 100 : 0 + const total = u.inputTokens + u.outputTokens; + const pct = maxTokens > 0 ? (total / maxTokens) * 100 : 0; return (
  1. @@ -35,7 +38,9 @@ export function TopUsersList({ users }: TopUsersListProps) {
    - {u.name} + + {u.name} + {formatTokens(total)} @@ -55,8 +60,8 @@ export function TopUsersList({ users }: TopUsersListProps) {
  2. - ) + ); })}
- ) + ); }