Files
ONE-OS/axhub-make/skills/ui-ux-pro-max/data/react-performance.csv
王冕 a27e3b8e43 feat: sync full workspace including web modules, docs, and configurations to Gitea
Optimized the root .gitignore to exclude virtual environments, node modules,
and temp folders to ensure clean and lightweight version tracking.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-09 18:12:25 +08:00

14 KiB

1NoCategoryIssueKeywordsPlatformDescriptionDoDon'tCode Example GoodCode Example BadSeverity
21Async WaterfallDefer Awaitasync await defer branchReact/Next.jsMove await into branches where actually used to avoid blocking unused code pathsMove await operations into branches where they're neededAwait at top of function blocking all branchesif (skip) return { skipped: true }; const data = await fetch()const data = await fetch(); if (skip) return { skipped: true }Critical
32Async WaterfallPromise.all Parallelpromise all parallel concurrentReact/Next.jsExecute independent async operations concurrently using Promise.all()Use Promise.all() for independent operationsSequential await for independent operationsconst [user, posts] = await Promise.all([fetchUser(), fetchPosts()])const user = await fetchUser(); const posts = await fetchPosts()Critical
43Async WaterfallDependency Parallelizationbetter-all dependency parallelReact/Next.jsUse better-all for operations with partial dependencies to maximize parallelismUse better-all to start each task at earliest possible momentWait for unrelated data before starting dependent fetchawait all({ user() {}, config() {}, profile() { return fetch((await this.$.user).id) } })const [user, config] = await Promise.all([...]); const profile = await fetchProfile(user.id)Critical
54Async WaterfallAPI Route Optimizationapi route waterfall promiseReact/Next.jsIn API routes start independent operations immediately even if not awaited yetStart promises early and await lateSequential awaits in API handlersconst sessionP = auth(); const configP = fetchConfig(); const session = await sessionPconst session = await auth(); const config = await fetchConfig()Critical
65Async WaterfallSuspense Boundariessuspense streaming boundaryReact/Next.jsUse Suspense to show wrapper UI faster while data loadsWrap async components in Suspense boundariesAwait data blocking entire page render<Suspense fallback={<Skeleton />}><DataDisplay /></Suspense>const data = await fetchData(); return <DataDisplay data={data} />High
76Bundle SizeBarrel Importsbarrel import direct pathReact/Next.jsImport directly from source files instead of barrel files to avoid loading unused modulesImport directly from source pathImport from barrel/index filesimport Check from 'lucide-react/dist/esm/icons/check'import { Check } from 'lucide-react'Critical
87Bundle SizeDynamic Importsdynamic import lazy nextReact/Next.jsUse next/dynamic to lazy-load large components not needed on initial renderUse dynamic() for heavy componentsImport heavy components at top levelconst Monaco = dynamic(() => import('./monaco'), { ssr: false })import { MonacoEditor } from './monaco-editor'Critical
98Bundle SizeDefer Third Partyanalytics defer third-partyReact/Next.jsLoad analytics and logging after hydration since they don't block interactionLoad non-critical scripts after hydrationInclude analytics in main bundleconst Analytics = dynamic(() => import('@vercel/analytics'), { ssr: false })import { Analytics } from '@vercel/analytics/react'Medium
109Bundle SizeConditional Loadingconditional module lazyReact/Next.jsLoad large data or modules only when a feature is activatedDynamic import when feature enabledImport large modules unconditionallyuseEffect(() => { if (enabled) import('./heavy.js') }, [enabled])import { heavyData } from './heavy.js'High
1110Bundle SizePreload Intentpreload hover focus intentReact/Next.jsPreload heavy bundles on hover/focus before they're neededPreload on user intent signalsLoad only on clickonMouseEnter={() => import('./editor')}onClick={() => import('./editor')}Medium
1211ServerReact.cache Dedupreact cache deduplicate requestReact/Next.jsUse React.cache() for server-side request deduplication within single requestWrap data fetchers with cache()Fetch same data multiple times in treeexport const getUser = cache(async () => await db.user.find())export async function getUser() { return await db.user.find() }Medium
1312ServerLRU Cache Cross-Requestlru cache cross requestReact/Next.jsUse LRU cache for data shared across sequential requestsUse LRU for cross-request cachingRefetch same data on every requestconst cache = new LRUCache({ max: 1000, ttl: 5*60*1000 })Always fetch from databaseHigh
1413ServerMinimize Serializationserialization rsc boundaryReact/Next.jsOnly pass fields that client actually uses across RSC boundariesPass only needed fields to client componentsPass entire objects to client<Profile name={user.name} /><Profile user={user} /> // 50 fields serializedHigh
1514ServerParallel Fetchingparallel fetch component compositionReact/Next.jsRestructure components to parallelize data fetching in RSCUse component composition for parallel fetchesSequential fetches in parent component<Header /><Sidebar /> // both fetch in parallelconst header = await fetchHeader(); return <><div>{header}</div><Sidebar /></>Critical
1615ServerAfter Non-blockingafter non-blocking loggingReact/Next.jsUse Next.js after() to schedule work after response is sentUse after() for logging/analyticsBlock response for non-critical operationsafter(async () => { await logAction() }); return Response.json(data)await logAction(); return Response.json(data)Medium
1716ClientSWR Deduplicationswr dedup cache revalidateReact/Next.jsUse SWR for automatic request deduplication and cachingUse useSWR for client data fetchingManual fetch in useEffectconst { data } = useSWR('/api/users', fetcher)useEffect(() => { fetch('/api/users').then(setUsers) }, [])Medium-High
1817ClientEvent Listener Dedupevent listener deduplicate globalReact/Next.jsShare global event listeners across component instancesUse useSWRSubscription for shared listenersRegister listener per component instanceuseSWRSubscription('global-keydown', () => { window.addEventListener... })useEffect(() => { window.addEventListener('keydown', handler) }, [])Low
1918RerenderDefer State Readsstate read callback subscriptionReact/Next.jsDon't subscribe to state only used in callbacksRead state on-demand in callbacksSubscribe to state used only in handlersconst handleClick = () => { const params = new URLSearchParams(location.search) }const params = useSearchParams(); const handleClick = () => { params.get('ref') }Medium
2019RerenderMemoized Componentsmemo extract expensiveReact/Next.jsExtract expensive work into memoized components for early returnsExtract to memo() componentsCompute expensive values before early returnconst UserAvatar = memo(({ user }) => ...); if (loading) return <Skeleton />const avatar = useMemo(() => compute(user)); if (loading) return <Skeleton />Medium
2120RerenderNarrow Dependencieseffect dependency primitiveReact/Next.jsSpecify primitive dependencies instead of objects in effectsUse primitive values in dependency arraysUse object references as dependenciesuseEffect(() => { console.log(user.id) }, [user.id])useEffect(() => { console.log(user.id) }, [user])Low
2221RerenderDerived Statederived boolean subscriptionReact/Next.jsSubscribe to derived booleans instead of continuous valuesUse derived boolean stateSubscribe to continuous valuesconst isMobile = useMediaQuery('(max-width: 767px)')const width = useWindowWidth(); const isMobile = width < 768Medium
2322RerenderFunctional setStatefunctional setstate callbackReact/Next.jsUse functional setState updates for stable callbacks and no stale closuresUse functional form: setState(curr => ...)Reference state directly in setStatesetItems(curr => [...curr, newItem])setItems([...items, newItem]) // items in depsMedium
2423RerenderLazy State Initusestate lazy initializationReact/Next.jsPass function to useState for expensive initial valuesUse function form for expensive initCompute expensive value directlyuseState(() => buildSearchIndex(items))useState(buildSearchIndex(items)) // runs every renderMedium
2524RerenderTransitionsstarttransition non-urgentReact/Next.jsMark frequent non-urgent state updates as transitionsUse startTransition for non-urgent updatesBlock UI on every state changestartTransition(() => setScrollY(window.scrollY))setScrollY(window.scrollY) // blocks on every scrollMedium
2625RenderingSVG Animation Wrappersvg animation wrapper divReact/Next.jsWrap SVG in div and animate wrapper for hardware accelerationAnimate div wrapper around SVGAnimate SVG element directly<div class='animate-spin'><svg>...</svg></div><svg class='animate-spin'>...</svg>Low
2726RenderingContent Visibilitycontent-visibility autoReact/Next.jsApply content-visibility: auto to defer off-screen renderingUse content-visibility for long listsRender all list items immediately.item { content-visibility: auto; contain-intrinsic-size: 0 80px }Render 1000 items without optimizationHigh
2827RenderingHoist Static JSXhoist static jsx elementReact/Next.jsExtract static JSX outside components to avoid re-creationHoist static elements to module scopeCreate static elements inside componentsconst skeleton = <div class='animate-pulse' />; function C() { return skeleton }function C() { return <div class='animate-pulse' /> }Low
2928RenderingHydration No Flickerhydration mismatch flickerReact/Next.jsUse inline script to set client-only data before hydrationInject sync script for client-only valuesUse useEffect causing flash<script dangerouslySetInnerHTML={{ __html: 'el.className = localStorage.theme' }} />useEffect(() => setTheme(localStorage.theme), []) // flickersMedium
3029RenderingConditional Renderconditional render ternaryReact/Next.jsUse ternary instead of && when condition can be 0 or NaNUse explicit ternary for conditionalsUse && with potentially falsy numbers{count > 0 ? <Badge>{count}</Badge> : null}{count && <Badge>{count}</Badge>} // renders '0'Low
3130RenderingActivity Componentactivity show hide preserveReact/Next.jsUse Activity component to preserve state/DOM for toggled componentsUse Activity for expensive toggle componentsUnmount/remount on visibility toggle<Activity mode={isOpen ? 'visible' : 'hidden'}><Menu /></Activity>{isOpen && <Menu />} // loses stateMedium
3231JS PerfBatch DOM CSSbatch dom css reflowReact/Next.jsGroup CSS changes via classes or cssText to minimize reflowsUse class toggle or cssTextChange styles one property at a timeelement.classList.add('highlighted')el.style.width='100px'; el.style.height='200px'Medium
3332JS PerfIndex Map Lookupmap index lookup findReact/Next.jsBuild Map for repeated lookups instead of multiple .find() callsBuild index Map for O(1) lookupsUse .find() in loopsconst byId = new Map(users.map(u => [u.id, u])); byId.get(id)users.find(u => u.id === order.userId) // O(n) each timeLow-Medium
3433JS PerfCache Property Accesscache property loopReact/Next.jsCache object property lookups in hot pathsCache values before loopsAccess nested properties in loopsconst val = obj.config.settings.value; for (...) process(val)for (...) process(obj.config.settings.value)Low-Medium
3534JS PerfCache Function Resultsmemoize cache functionReact/Next.jsUse module-level Map to cache repeated function resultsUse Map cache for repeated callsRecompute same values repeatedlyconst cache = new Map(); if (cache.has(x)) return cache.get(x)slugify(name) // called 100 times same inputMedium
3635JS PerfCache Storage APIlocalstorage cache readReact/Next.jsCache localStorage/sessionStorage reads in memoryCache storage reads in MapRead storage on every callif (!cache.has(key)) cache.set(key, localStorage.getItem(key))localStorage.getItem('theme') // every callLow-Medium
3736JS PerfCombine Iterationscombine filter map loopReact/Next.jsCombine multiple filter/map into single loopSingle loop for multiple categorizationsChain multiple filter() callsfor (u of users) { if (u.isAdmin) admins.push(u); if (u.isTester) testers.push(u) }users.filter(admin); users.filter(tester); users.filter(inactive)Low-Medium
3837JS PerfLength Check Firstlength check array compareReact/Next.jsCheck array lengths before expensive comparisonsEarly return if lengths differAlways run expensive comparisonif (a.length !== b.length) return true; // then comparea.sort().join() !== b.sort().join() // even when lengths differMedium-High
3938JS PerfEarly Returnearly return exit functionReact/Next.jsReturn early when result is determined to skip processingReturn immediately on first errorProcess all items then check errorsfor (u of users) { if (!u.email) return { error: 'Email required' } }let hasError; for (...) { if (!email) hasError=true }; if (hasError)...Low-Medium
4039JS PerfHoist RegExpregexp hoist moduleReact/Next.jsDon't create RegExp inside render - hoist or memoizeHoist RegExp to module scopeCreate RegExp every renderconst EMAIL_RE = /^[^@]+@[^@]+$/; function validate() { EMAIL_RE.test(x) }function C() { const re = new RegExp(pattern); re.test(x) }Low-Medium
4140JS PerfLoop Min Maxloop min max sortReact/Next.jsUse loop for min/max instead of sort - O(n) vs O(n log n)Single pass loop for min/maxSort array to find min/maxlet max = arr[0]; for (x of arr) if (x > max) max = xarr.sort((a,b) => b-a)[0] // O(n log n)Low
4241JS PerfSet Map Lookupsset map includes hasReact/Next.jsUse Set/Map for O(1) lookups instead of array.includes()Convert to Set for membership checksUse .includes() for repeated checksconst allowed = new Set(['a','b']); allowed.has(id)const allowed = ['a','b']; allowed.includes(id)Low-Medium
4342JS PerftoSorted Immutabletosorted sort immutableReact/Next.jsUse toSorted() instead of sort() to avoid mutating arraysUse toSorted() for immutabilityMutate arrays with sort()users.toSorted((a,b) => a.name.localeCompare(b.name))users.sort((a,b) => a.name.localeCompare(b.name)) // mutatesMedium-High
4443AdvancedEvent Handler Refsuseeffectevent ref handlerReact/Next.jsStore callbacks in refs for stable effect subscriptionsUse useEffectEvent for stable handlersRe-subscribe on every callback changeconst onEvent = useEffectEvent(handler); useEffect(() => { listen(onEvent) }, [])useEffect(() => { listen(handler) }, [handler]) // re-subscribesLow
4544AdvanceduseLatest Hookuselatest ref callbackReact/Next.jsAccess latest values in callbacks without adding to dependency arraysUse useLatest for fresh values in stable callbacksAdd callback to effect dependenciesconst cbRef = useLatest(cb); useEffect(() => { setTimeout(() => cbRef.current()) }, [])useEffect(() => { setTimeout(() => cb()) }, [cb]) // re-runsLow