react-core

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

React Core Best Practices

React核心最佳实践

Comprehensive React development guidelines with Vercel optimization patterns.
包含Vercel优化模式的全面React开发指南。

Instructions

说明

1. Component Structure

1. 组件结构

tsx
// ✅ Max 200 lines per component
// ✅ Single responsibility

interface Props {
  user: User;
  onUpdate: (user: User) => void;
}

export function UserCard({ user, onUpdate }: Props) {
  // Hooks first
  const [isEditing, setIsEditing] = useState(false);
  
  // Derived state (no useState needed)
  const fullName = `${user.firstName} ${user.lastName}`;
  
  // Event handlers
  const handleSubmit = () => { ... };
  
  // Render
  return (
    <div className="user-card">
      <h2>{fullName}</h2>
      ...
    </div>
  );
}
tsx
// ✅ 每个组件最多200行代码
// ✅ 单一职责

interface Props {
  user: User;
  onUpdate: (user: User) => void;
}

export function UserCard({ user, onUpdate }: Props) {
  // Hooks 放在最前面
  const [isEditing, setIsEditing] = useState(false);
  
  // 派生状态(无需useState)
  const fullName = `${user.firstName} ${user.lastName}`;
  
  // 事件处理函数
  const handleSubmit = () => { ... };
  
  // 渲染部分
  return (
    <div className="user-card">
      <h2>{fullName}</h2>
      ...
    </div>
  );
}

2. Derived State (No useState)

2. 派生状态(无需useState)

tsx
// ❌ Bad - unnecessary state
const [fullName, setFullName] = useState('');
useEffect(() => {
  setFullName(`${firstName} ${lastName}`);
}, [firstName, lastName]);

// ✅ Good - derived state
const fullName = `${firstName} ${lastName}`;

// ✅ Good - expensive computation
const sortedItems = useMemo(
  () => items.sort((a, b) => a.name.localeCompare(b.name)),
  [items]
);
tsx
// ❌ 错误示例 - 不必要的状态
const [fullName, setFullName] = useState('');
useEffect(() => {
  setFullName(`${firstName} ${lastName}`);
}, [firstName, lastName]);

// ✅ 正确示例 - 派生状态
const fullName = `${firstName} ${lastName}`;

// ✅ 正确示例 - 耗时计算场景
const sortedItems = useMemo(
  () => items.sort((a, b) => a.name.localeCompare(b.name)),
  [items]
);

3. Functional setState

3. 函数式setState

tsx
// ❌ Bad - stale state risk
setCount(count + 1);

// ✅ Good - always current
setCount(prev => prev + 1);

// ✅ Good - object state
setUser(prev => ({ ...prev, name: newName }));
tsx
// ❌ 错误示例 - 存在状态过期风险
setCount(count + 1);

// ✅ 正确示例 - 始终获取最新状态
setCount(prev => prev + 1);

// ✅ 正确示例 - 对象类型状态
setUser(prev => ({ ...prev, name: newName }));

4. Prevent Unnecessary Re-renders

4. 避免不必要的重渲染

tsx
// ✅ Primitive dependencies for useMemo
const result = useMemo(() => {
  return expensiveCalculation(id);
}, [id]); // id is primitive

// ✅ Stable callback references
const handleClick = useCallback(() => {
  doSomething(id);
}, [id]);

// ✅ Memoize child components
const MemoizedChild = memo(ChildComponent);
tsx
// ✅ useMemo使用原始类型依赖项
const result = useMemo(() => {
  return expensiveCalculation(id);
}, [id]); // id是原始类型

// ✅ 稳定的回调引用
const handleClick = useCallback(() => {
  doSomething(id);
}, [id]);

// ✅ 对子组件进行记忆化处理
const MemoizedChild = memo(ChildComponent);

5. Event Handlers

5. 事件处理函数

tsx
// ❌ Bad - creates new function each render
<button onClick={() => handleClick(item.id)}>

// ✅ Good - stable reference with data attribute
<button data-id={item.id} onClick={handleClick}>

function handleClick(e: React.MouseEvent<HTMLButtonElement>) {
  const id = e.currentTarget.dataset.id;
  // ...
}
tsx
// ❌ 错误示例 - 每次渲染都会创建新函数
<button onClick={() => handleClick(item.id)}>

// ✅ 正确示例 - 使用数据属性保持稳定引用
<button data-id={item.id} onClick={handleClick}>

function handleClick(e: React.MouseEvent<HTMLButtonElement>) {
  const id = e.currentTarget.dataset.id;
  // ...
}

6. Custom Hooks

6. 自定义Hooks

tsx
// ✅ Extract reusable logic
function useLocalStorage<T>(key: string, initialValue: T) {
  const [value, setValue] = useState<T>(() => {
    const stored = localStorage.getItem(key);
    return stored ? JSON.parse(stored) : initialValue;
  });

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);

  return [value, setValue] as const;
}
tsx
// ✅ 提取可复用逻辑
function useLocalStorage<T>(key: string, initialValue: T) {
  const [value, setValue] = useState<T>(() => {
    const stored = localStorage.getItem(key);
    return stored ? JSON.parse(stored) : initialValue;
  });

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);

  return [value, setValue] as const;
}

7. Props Pattern

7. Props模式

tsx
// ✅ Destructure props
function Button({ children, variant = 'primary', ...rest }: ButtonProps) {
  return (
    <button className={`btn-${variant}`} {...rest}>
      {children}
    </button>
  );
}
tsx
// ✅ 解构Props
function Button({ children, variant = 'primary', ...rest }: ButtonProps) {
  return (
    <button className={`btn-${variant}`} {...rest}>
      {children}
    </button>
  );
}

8. Loading & Error States

8. 加载与错误状态

tsx
function UserProfile({ userId }: Props) {
  const { data, isLoading, error } = useUser(userId);

  if (isLoading) return <Skeleton />;
  if (error) return <ErrorMessage error={error} />;
  if (!data) return <NotFound />;

  return <UserCard user={data} />;
}
tsx
function UserProfile({ userId }: Props) {
  const { data, isLoading, error } = useUser(userId);

  if (isLoading) return <Skeleton />;
  if (error) return <ErrorMessage error={error} />;
  if (!data) return <NotFound />;

  return <UserCard user={data} />;
}

References

参考资料