AGENT SKILL

trove-react

React 19 coding conventions and performance patterns. Auto-activates when working with React/TypeScript files. Covers hooks, state management, TanStack Query, Zustand, immutable updates, and component conventions.

License 许可
MIT
所属仓库
bravew/trove
最近更新
2026-11-12
Stars
★ 10
Forks
1

01 前言 Front Matter

name
trove-react
paths
[ "**/*.tsx", "**/*.jsx" ]
metadata
{ "trove-category": "code", "trove-category-label": "Code" }
description
React 19 coding conventions and performance patterns. Auto-activates when working with React/TypeScript files. Covers hooks, state management, TanStack Query, Zustand, immutable updates, and component conventions.
when_to_use
react component; react hooks; tanstack query; zustand state
user-invocable
false

03 SKILL.md 正文

<!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly --> <!-- Regenerate: bun run build:skills -->

Session Init

This skill ships Trove conventions. Prefer existing project patterns over generic best practices when they conflict.

React 19 Conventions

Immutable State Updates (CRITICAL)

React StrictMode double-invokes state updaters. Mutating objects causes duplicated side effects.

// BAD — mutation causes bugs in StrictMode
setMessages(prev => {
  prev[prev.length - 1].text += content; // MUTATION!
  return [...prev];
});

// GOOD — immutable update
setMessages(prev => {
  const updated = [...prev];
  const lastIndex = updated.length - 1;
  updated[lastIndex] = { ...updated[lastIndex], text: updated[lastIndex].text + content };
  return updated;
});

Zustand Selectors (CRITICAL)

Always use selectors — never destructure the store directly:

// BAD — subscribes to entire store, re-renders on ANY change
const { darkMode } = useGlobalStore();

// GOOD — subscribes only to darkMode
const darkMode = useGlobalStore(state => state.darkMode);

// GOOD — multiple values with useShallow
import { useShallow } from 'zustand/shallow';
const { username, email } = useUserStore(
  useShallow(state => ({ username: state.username, email: state.email }))
);

Component Patterns

  • Prefer function components with hooks
  • Use React.memo() only when profiling shows re-render cost
  • Extract custom hooks for reusable logic
  • Keep components under 200 lines — split into sub-components

TanStack Query

// Queries — always provide staleTime
const { data, isLoading } = useQuery({
  queryKey: ['users', userId],
  queryFn: () => fetchUser(userId),
  staleTime: 5 * 60 * 1000,
});

// Mutations — invalidate related queries on success
const mutation = useMutation({
  mutationFn: updateUser,
  onSuccess: () => queryClient.invalidateQueries({ queryKey: ['users'] }),
});

Error Boundaries

Wrap route-level components with error boundaries. Never let errors crash the full app.

AI Gotchas

  • useEffect dependencies: Always include all referenced values in the dependency array
  • Ref vs State: Use useRef for values that don't trigger re-renders (timers, DOM refs)
  • Key prop: Use stable, unique IDs — never use array index as key for dynamic lists
  • Event handlers: Define inline only for simple logic; extract for complex handlers

04 同仓库更多 Skills