Token导航 LogoToken导航TokenDH.com
开发规范需要联网github未标认证来源可访问clear审计未展示

react-best-practicesReact 最佳实践

Agent Skill

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。它适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码,整理组件结构,或定位布局和性能问题。使用时需要结合项目现有设计系统、路由和构建方式,避免只生成孤立片段;涉及页面改动时,应配合本地预览和构建检查确认视觉效果。

总安装

436

周安装

18

GitHub Stars

公开资料未说明

下载量

143
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:react-best-practices(React 最佳实践)
来源仓库:https://github.com/5dlabs/cto
仓库路径:skills/react-best-practices
安装命令:
npx skills add 5dlabs/cto --skill "react-best-practices"
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

AgentSkills.tonpx skills
npx skills add 5dlabs/cto --skill "react-best-practices"

简介

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。

  • 适合生成或审查 React、Next.js、Vue、Tailwind、CSS 等代码,整理组件结构或定位布局问题。
  • 需结合项目设计系统、路由和构建方式使用,避免生成孤立片段;改动页面时应配合本地预览确认效果。
  • 安装命令:npx skills add 5dlabs/cto --skill "react-best-practices",来源仓库:https://github.com/5dlabs/cto/tree/main/skills/react-best-practices。
  • 建议确认权限范围和维护状态,涉及文件读写时注意操作边界。

SKILL.md

React Best Practices

Comprehensive performance optimization guide for React and Next.js applications. Contains 45+ rules across 8 categories, prioritized by impact.

When to Use

Reference these guidelines when:

  • Writing new React components or Next.js pages
  • Implementing data fetching (client or server-side)
  • Reviewing code for performance issues
  • Refactoring existing React/Next.js code
  • Optimizing bundle size or load times

Relevant Agents: Blaze (React/Next.js), Spark (Electron), Tap (Expo/React Native)


Rule Categories by Priority

PriorityCategoryImpact
1Eliminating WaterfallsCRITICAL
2Bundle Size OptimizationCRITICAL
3Server-Side PerformanceHIGH
4Client-Side Data FetchingMEDIUM-HIGH
5Re-render OptimizationMEDIUM
6Rendering PerformanceMEDIUM
7JavaScript PerformanceLOW-MEDIUM

1. Eliminating Waterfalls (CRITICAL)

Waterfalls are the #1 performance killer. Fix these first.

Move await into branches

Bad:

async function handleRequest(userId: string, skipProcessing: boolean) {
  const userData = await fetchUserData(userId);  // Always waits

  if (skipProcessing) {
    return { skipped: true };  // Waited for nothing
  }

  return processUserData(userData);
}

Good:

async function handleRequest(userId: string, skipProcessing: boolean) {
  if (skipProcessing) {
    return { skipped: true };  // Returns immediately
  }

  const userData = await fetchUserData(userId);
  return processUserData(userData);
}

Parallelize independent operations

Bad:

const user = await fetchUser(id);
const posts = await fetchPosts(id);
const comments = await fetchComments(id);
// Total time: user + posts + comments

Good:

const [user, posts, comments] = await Promise.all([
  fetchUser(id),
  fetchPosts(id),
  fetchComments(id),
]);
// Total time: max(user, posts, comments)

Start promises early, await late

Bad:

export async function GET() {
  const data = await fetchData();  // Blocks immediately
  const transformed = transform(data);
  return Response.json(transformed);
}

Good:

export async function GET() {
  const dataPromise = fetchData();  // Start immediately
  // ... do other setup work ...
  const data = await dataPromise;   // Await when needed
  return Response.json(transform(data));
}

Use Suspense boundaries for streaming

<Suspense fallback={<Loading />}>
  <SlowComponent />
</Suspense>

2. Bundle Size Optimization (CRITICAL)

Every KB matters for initial load.

Import directly, avoid barrel files

Bad:

import { Button } from '@/components';  // Pulls entire barrel

Good:

import { Button } from '@/components/Button';  // Only Button

Use dynamic imports for heavy components

Bad:

import { HeavyChart } from './HeavyChart';

function Dashboard() {
  return showChart ? <HeavyChart /> : null;
}

Good:

import dynamic from 'next/dynamic';

const HeavyChart = dynamic(() => import('./HeavyChart'), {
  loading: () => <ChartSkeleton />,
});

function Dashboard() {
  return showChart ? <HeavyChart /> : null;
}

Defer third-party scripts

Bad:

import { Analytics } from '@analytics/lib';

function App() {
  useEffect(() => {
    Analytics.init();  // Blocks hydration
  }, []);
}

Good:

function App() {
  useEffect(() => {
    // Load after hydration
    import('@analytics/lib').then(({ Analytics }) => {
      Analytics.init();
    });
  }, []);
}

Preload on hover/focus

function Link({ href, children }) {
  const preload = () => {
    const link = document.createElement('link');
    link.rel = 'prefetch';
    link.href = href;
    document.head.appendChild(link);
  };

  return (
    <a href={href} onMouseEnter={preload} onFocus={preload}>
      {children}
    </a>
  );
}

3. Server-Side Performance (HIGH)

Use React.cache() for per-request deduplication

import { cache } from 'react';

const getUser = cache(async (id: string) => {
  return await db.user.findUnique({ where: { id } });
});

// Multiple components can call getUser(id) - only one DB query

Minimize data passed to client components

Bad:

// Server Component
async function UserPage({ id }) {
  const user = await getFullUser(id);  // 50 fields
  return <ClientProfile user={user} />;
}

Good:

// Server Component
async function UserPage({ id }) {
  const user = await getFullUser(id);
  return (
    <ClientProfile
      name={user.name}
      avatar={user.avatar}
      // Only what client needs
    />
  );
}

Use after() for non-blocking operations

import { after } from 'next/server';

export async function POST(request: Request) {
  const data = await request.json();
  const result = await saveToDb(data);

  after(async () => {
    await sendAnalytics(result);
    await notifyWebhooks(result);
  });

  return Response.json(result);  // Returns immediately
}

4. Client-Side Data Fetching (MEDIUM-HIGH)

Use SWR for automatic deduplication

import useSWR from 'swr';

function useUser(id: string) {
  return useSWR(`/api/users/${id}`, fetcher, {
    dedupingInterval: 2000,  // Dedup requests within 2s
  });
}

// Multiple components using useUser(same-id) = one request

Deduplicate global event listeners

Bad:

function Component() {
  useEffect(() => {
    window.addEventListener('resize', handler);  // Each instance adds one
    return () => window.removeEventListener('resize', handler);
  }, []);
}

Good:

// Shared hook with ref counting
const listeners = new Set();

function useWindowResize(handler: () => void) {
  useEffect(() => {
    listeners.add(handler);
    if (listeners.size === 1) {
      window.addEventListener('resize', notifyAll);
    }
    return () => {
      listeners.delete(handler);
      if (listeners.size === 0) {
        window.removeEventListener('resize', notifyAll);
      }
    };
  }, [handler]);
}

5. Re-render Optimization (MEDIUM)

Don't subscribe to state only used in callbacks

Bad:

function Form() {
  const [value, setValue] = useState('');  // Re-renders on every keystroke

  const handleSubmit = () => {
    submitForm(value);
  };

  return <input onChange={e => setValue(e.target.value)} />;
}

Good:

function Form() {
  const valueRef = useRef('');

  const handleSubmit = () => {
    submitForm(valueRef.current);
  };

  return <input onChange={e => { valueRef.current = e.target.value }} />;
}

Extract expensive work into memoized components

Bad:

function Parent({ data, filter }) {
  return (
    <div>
      <ExpensiveList data={data} />  {/* Re-renders when filter changes */}
      <Filter value={filter} />
    </div>
  );
}

Good:

const MemoizedList = memo(ExpensiveList);

function Parent({ data, filter }) {
  return (
    <div>
      <MemoizedList data={data} />  {/* Only re-renders when data changes */}
      <Filter value={filter} />
    </div>
  );
}

Use functional setState for stable callbacks

Bad:

const increment = useCallback(() => {
  setCount(count + 1);  // Dependency on count
}, [count]);

Good:

const increment = useCallback(() => {
  setCount(c => c + 1);  // No dependencies
}, []);

Use startTransition for non-urgent updates

import { startTransition } from 'react';

function SearchBox() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);

  const handleChange = (e) => {
    setQuery(e.target.value);  // Urgent: update input

    startTransition(() => {
      setResults(search(e.target.value));  // Non-urgent: can be interrupted
    });
  };
}

6. Rendering Performance (MEDIUM)

Animate wrapper divs, not SVG elements

Bad:

<motion.svg animate={{ scale: 1.2 }}>  {/* Triggers SVG recalc */}
  <path d="..." />
</motion.svg>

Good:

<motion.div animate={{ scale: 1.2 }}>  {/* GPU accelerated */}
  <svg><path d="..." /></svg>
</motion.div>

Use content-visibility for long lists

.list-item {
  content-visibility: auto;
  contain-intrinsic-size: 0 50px;
}

Extract static JSX outside components

Bad:

function Component() {
  return (
    <div>
      <header>Static Header</header>  {/* Recreated every render */}
      <DynamicContent />
    </div>
  );
}

Good:

const StaticHeader = <header>Static Header</header>;

function Component() {
  return (
    <div>
      {StaticHeader}  {/* Same reference */}
      <DynamicContent />
    </div>
  );
}

Use ternary, not && for conditionals

Bad:

{items.length && <List items={items} />}  // Renders "0" when empty

Good:

{items.length > 0 ? <List items={items} /> : null}

7. JavaScript Performance (LOW-MEDIUM)

Build Map for repeated lookups

Bad:

users.forEach(user => {
  const role = roles.find(r => r.userId === user.id);  // O(n) each time
});

Good:

const roleMap = new Map(roles.map(r => [r.userId, r]));
users.forEach(user => {
  const role = roleMap.get(user.id);  // O(1)
});

Combine multiple iterations

Bad:

const active = users.filter(u => u.active);
const names = active.map(u => u.name);
const sorted = names.sort();
// 3 iterations

Good:

const names = [];
for (const u of users) {
  if (u.active) names.push(u.name);
}
names.sort();
// 1 iteration + sort

Check length before expensive operations

Bad:

if (items.some(item => expensiveCheck(item))) { ... }

Good:

if (items.length > 0 && items.some(item => expensiveCheck(item))) { ... }

Use Set/Map for O(1) lookups

Bad:

const isSelected = selectedIds.includes(id);  // O(n)

Good:

const selectedSet = new Set(selectedIds);
const isSelected = selectedSet.has(id);  // O(1)

Quick Reference Checklist

Before submitting React/Next.js code:

Critical (Fix First)

  • No sequential awaits for independent operations
  • Dynamic imports for components >50KB
  • No barrel file imports in hot paths
  • Third-party scripts loaded after hydration

High Priority

  • Server components minimize client-passed data
  • React.cache() for repeated data fetches
  • Proper Suspense boundaries

Medium Priority

  • Memoized expensive components
  • Stable callback references (functional setState)
  • No unnecessary re-renders from state subscriptions

Related Skills

  • test-driven-development - TDD for React components
  • verification-before-completion - Verify bundle size, performance metrics

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Claude Code

30.86%
按下载量换算44

OpenCode

22.09%
按下载量换算32

Codex

17.49%
按下载量换算25

Gemini CLI

12.38%
按下载量换算18

windsurf

7.95%
按下载量换算11

trae

3.16%
按下载量换算5

安全审计

暂无安全审计结果可展示。

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills