mcpField

react

github.com/squirrelfishcityhall150开发35 次安装
代码仓库

关于 react

面向 React 开发者的参考技能,涵盖 React 19、Hooks、Suspense、懒加载、TypeScript 和性能模式,并提供组件实践、常见错误与项目组织建议。

主要功能

  1. 01React 19 组件模式
  2. 02Hooks 与状态管理指导
  3. 03Suspense 与懒加载
  4. 04TypeScript 组件模式
  5. 05性能优化建议
  6. 06常见错误与文件组织

适用场景

  1. 01创建类型化 React 组件
  2. 02拆分较重功能的代码
  3. 03使用 Suspense 处理异步界面
  4. 04检查 Hooks 与渲染性能

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/squirrelfishcityhall150/claude-code-kit --skill react

安装后在 Claude Code 中输入/react确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

skill-rules-fragment.json
resources/
component-patterns.md
hooks-patterns.md
performance.md
typescript-patterns.md

详细介绍

React 核心模式

目的

使用 hooks、Suspense、懒加载和 TypeScript 构建现代应用所需的 React 19 基本模式。

注意:React 19(于 2024 年 12 月发布)的破坏性变更:

  • 不再需要 forwardRef——直接将 ref 作为 prop 传递
  • 已移除 propTypes(会被静默忽略)
  • 必须使用新的 JSX 转换
  • 不建议使用 React.FC 类型——改用直接定义的函数组件

何时使用此技能

  • 创建 React 组件
  • 使用 React hooks(useState、useEffect、useCallback、useMemo)
  • 实现懒加载和代码拆分
  • 使用 Suspense 边界
  • 使用 React 专属的 TypeScript 模式
  • 使用 React 进行性能优化

快速入门

组件结构模板
import { useState, useCallback } from 'react';

interface Props {
  userId: string;
  onUpdate?: (data: UserData) => void;
}

interface UserData {
  name: string;
  email: string;
}

function UserProfile({ userId, onUpdate }: Props) {
  const [data, setData] = useState<UserData | null>(null);

  const handleUpdate = useCallback((newData: UserData) => {
    setData(newData);
    onUpdate?.(newData);
  }, [onUpdate]);

  return (
    <div>
      {/* Component content */}
    </div>
  );
}

export default UserProfile;
组件检查清单

创建 React 组件时,请遵循以下事项:

  • 使用带类型 props 的函数组件(而不是 React.FC)
  • 为 Props 和本地状态定义接口
  • 对传递给子组件的事件处理函数使用 useCallback
  • 对开销较大的计算使用 useMemo
  • 如果组件较重,则使用懒加载:lazy(() => import())
  • 使用带备用内容的 <Suspense> 包裹懒加载组件
  • 在底部进行默认导出
  • 不要有条件地调用 hooks(必须始终按相同顺序调用)
  • 将 ref 作为 prop 传递(React 19 中不再需要 forwardRef)

核心 Hooks 模式

useState
// Simple state
const [count, setCount] = useState<number>(0);

// Object state
const [user, setUser] = useState<User | null>(null);

// Array state
const [items, setItems] = useState<Item[]>([]);

// Functional updates when depending on previous state
setCount(prev => prev + 1);
setItems(prev => [...prev, newItem]);
useCallback
// Wrap functions passed to child components
const handleClick = useCallback((id: string) => {
  console.log('Clicked:', id);
}, []); // Empty deps if no dependencies

// With dependencies
const handleUpdate = useCallback((data: FormData) => {
  apiCall(userId, data);
}, [userId]); // Re-create when userId changes
useMemo
// Expensive computation
const sortedItems = useMemo(() => {
  return items.sort((a, b) => a.score - b.score);
}, [items]);

// Derived state
const totalPrice = useMemo(() => {
  return cart.reduce((sum, item) => sum + item.price, 0);
}, [cart]);
useEffect
// Run once on mount
useEffect(() => {
  fetchData();
}, []);

// Run when dependency changes
useEffect(() => {
  if (userId) {
    loadUserData(userId);
  }
}, [userId]);

// Cleanup
useEffect(() => {
  const subscription = subscribe(userId);
  return () => subscription.unsubscribe();
}, [userId]);

懒加载与代码拆分

基本懒加载
import React, { Suspense } from 'react';

// Lazy load heavy component
const HeavyChart = React.lazy(() => import('./HeavyChart'));

function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>
      <Suspense fallback={<div>Loading chart...</div>}>
        <HeavyChart />
      </Suspense>
    </div>
  );
}
多个懒加载组件
const AdminPanel = React.lazy(() => import('./AdminPanel'));
const UserSettings = React.lazy(() => import('./UserSettings'));
const Reports = React.lazy(() => import('./Reports'));

function App() {
  return (
    <Suspense fallback={<LoadingSpinner />}>
      <Routes>
        <Route path="/admin" element={<AdminPanel />} />
        <Route path="/settings" element={<UserSettings />} />
        <Route path="/reports" element={<Reports />} />
      </Routes>
    </Suspense>
  );
}
基于功能的代码拆分
// features/auth/index.tsx
export { default } from './AuthFeature';

// Lazy load entire feature
const AuthFeature = React.lazy(() => import('~/features/auth'));

<Suspense fallback={<FeatureLoader />}>
  <AuthFeature />
</Suspense>

Suspense 模式

Suspense 边界
// Wrap data-fetching components
<Suspense fallback={<Skeleton />}>
  <UserProfile userId={id} />
</Suspense>

// Nested Suspense for granular loading
<Suspense fallback={<PageLoader />}>
  <Header />
  <Suspense fallback={<ContentSkeleton />}>
    <MainContent />
  </Suspense>
  <Footer />
</Suspense>
使用 Suspense 的错误边界
import { ErrorBoundary } from 'react-error-boundary';

<ErrorBoundary fallback={<ErrorFallback />}>
  <Suspense fallback={<Loading />}>
    <DataComponent />
  </Suspense>
</ErrorBoundary>

TypeScript 模式

组件 Props
// Basic props
interface ButtonProps {
  label: string;
  onClick: () => void;
  disabled?: boolean;
}

// Props with children
interface CardProps {
  title: string;
  children: React.ReactNode;
}

// Props with specific child types
interface ListProps {
  children: React.ReactElement<ItemProps> | React.ReactElement<ItemProps>[];
}

// Props with event handlers
interface FormProps {
  onSubmit: (data: FormData) => void;
  onChange?: (field: string, value: unknown) => void;
}
Hooks 与 TypeScript
// useState with type
const [user, setUser] = useState<User | null>(null);
const [items, setItems] = useState<Item[]>([]);

// useRef with type
const inputRef = useRef<HTMLInputElement>(null);
const timerRef = useRef<number | null>(null);

// Custom hook with return type
function useUser(id: string): { user: User | null; loading: boolean } {
  const [user, setUser] = useState<User | null>(null);
  const [loading, setLoading] = useState(true);

  // ... implementation

  return { user, loading };
}

性能优化

React.memo
// Memoize component to prevent unnecessary re-renders
const UserCard = React.memo<UserCardProps>(({ user, onUpdate }) => {
  return (
    <div>
      <h3>{user.name}</h3>
      <button onClick={() => onUpdate(user.id)}>Update</button>
    </div>
  );
});

// Custom comparison function
const UserCard = React.memo(UserCardComponent, (prevProps, nextProps) => {
  return prevProps.user.id === nextProps.user.id;
});
避免重新渲染
// ❌ Bad: Creates new function on every render
function Parent() {
  return <Child onClick={() => console.log('clicked')} />;
}

// ✅ Good: Stable function reference
function Parent() {
  const handleClick = useCallback(() => {
    console.log('clicked');
  }, []);

  return <Child onClick={handleClick} />;
}

常见模式

条件渲染
// Ternary operator
{isLoading ? <Spinner /> : <Content />}

// Logical AND
{error && <ErrorMessage error={error} />}

// Nullish coalescing
{user ?? <GuestView />}

// Early return for loading states
function Component() {
  const { data } = useSomeHook();

  // ❌ Avoid early returns for loading - breaks hooks rules
  // Use Suspense instead

  return <div>{data.map(...)}</div>;
}
列表与键
// Always use stable keys
{items.map(item => (
  <ItemCard key={item.id} item={item} />
))}

// Never use index as key if list can reorder
// ❌ Bad
{items.map((item, index) => (
  <ItemCard key={index} item={item} />
))}

文件组织

基于功能的结构
src/
├── features/
│   ├── auth/
│   │   ├── components/
│   │   ├── hooks/
│   │   ├── types/
│   │   └── index.tsx
│   └── posts/
│       ├── components/
│       ├── hooks/
│       ├── types/
│       └── index.tsx
├── components/  # Shared components
├── hooks/       # Shared hooks
└── types/       # Shared types
组件就近组织
features/posts/
├── components/
│   ├── PostCard.tsx
│   ├── PostList.tsx
│   └── PostForm.tsx
├── hooks/
│   ├── usePost.ts
│   └── usePosts.ts
├── types/
│   └── post.ts
└── index.tsx  # Public API

应避免的常见错误

1. 条件调用 Hooks
// ❌ Never do this
function Component({ condition }) {
  if (condition) {
    const [state, setState] = useState(0); // Breaks rules of hooks
  }
}

// ✅ Do this
function Component({ condition }) {
  const [state, setState] = useState(0);
  // Use state conditionally, not the hook
}
2. 缺少依赖项
// ❌ Bad: Missing dependency
useEffect(() => {
  fetchUser(userId);
}, []); // userId should be in deps

// ✅ Good: All dependencies listed
useEffect(() => {
  fetchUser(userId);
}, [userId]);
3. 修改状态
// ❌ Bad: Mutating state directly
const handleAdd = () => {
  items.push(newItem); // Don't mutate
  setItems(items);
};

// ✅ Good: Create new array
const handleAdd = () => {
  setItems([...items, newItem]);
};

其他资源

如需了解更详细的模式,请参阅:

评论

支持 Markdown