react-useeffect-audit

Identify and fix unnecessary useEffect usage in React code. Use when reviewing React code that uses Effects, when asked to optimize React components, when seeing patterns like "useEffect + setState", when users ask about Effect best practices, or when refactoring React code. Helps eliminate redundant renders and simplify component logic.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "react-useeffect-audit" with this command: npx skills add mpoc/skills/mpoc-skills-react-useeffect-audit

React useEffect Audit

Effects are an escape hatch for synchronizing with external systems (DOM, network, third-party widgets). If no external system is involved, you likely don't need an Effect.

Quick Decision Guide

ScenarioUse Effect?Alternative
Transform data for renderingNoCalculate during render
Handle user eventsNoEvent handler
Cache expensive calculationsNouseMemo
Reset state when props changeNokey prop
Adjust state based on propsNoCalculate during render
Chain of state updatesNoSingle event handler
Notify parent of state changeNoCall parent in event handler
Initialize app (once)NoModule-level code
Subscribe to external storeNouseSyncExternalStore
Fetch data on mount/changeYesWith cleanup; prefer framework

Common Anti-Patterns

1. Derived State in Effect

// ❌ Bad: Extra render, unnecessary state
const [fullName, setFullName] = useState('');
useEffect(() => {
  setFullName(firstName + ' ' + lastName);
}, [firstName, lastName]);

// ✅ Good: Calculate during render
const fullName = firstName + ' ' + lastName;

2. Event Logic in Effect

// ❌ Bad: Runs on mount if condition true, not just on click
useEffect(() => {
  if (product.isInCart) {
    showNotification('Added to cart!');
  }
}, [product]);

// ✅ Good: In event handler
function handleBuyClick() {
  addToCart(product);
  showNotification('Added to cart!');
}

3. Expensive Calculations

// ❌ Bad: Unnecessary state and Effect
const [filtered, setFiltered] = useState([]);
useEffect(() => {
  setFiltered(getFilteredTodos(todos, filter));
}, [todos, filter]);

// ✅ Good: useMemo for expensive calculations
const filtered = useMemo(
  () => getFilteredTodos(todos, filter),
  [todos, filter]
);

4. Resetting State on Prop Change

// ❌ Bad: Effect to reset state
function ProfilePage({ userId }) {
  const [comment, setComment] = useState('');
  useEffect(() => {
    setComment('');
  }, [userId]);
}

// ✅ Good: Use key to create fresh instance
<Profile userId={userId} key={userId} />

5. Effect Chains

// ❌ Bad: Multiple Effects triggering each other
useEffect(() => {
  if (card?.gold) setGoldCount(c => c + 1);
}, [card]);
useEffect(() => {
  if (goldCount > 3) { setRound(r => r + 1); setGoldCount(0); }
}, [goldCount]);

// ✅ Good: Calculate in event handler
function handlePlaceCard(nextCard) {
  setCard(nextCard);
  if (nextCard.gold) {
    if (goldCount < 3) setGoldCount(goldCount + 1);
    else { setGoldCount(0); setRound(round + 1); }
  }
}

6. Notifying Parent

// ❌ Bad: Effect to notify parent
useEffect(() => {
  onChange(isOn);
}, [isOn, onChange]);

// ✅ Good: Notify in same event
function handleClick() {
  setIsOn(!isOn);
  onChange(!isOn);
}

// ✅ Better: Controlled component (parent owns state)
function Toggle({ isOn, onChange }) {
  return <button onClick={() => onChange(!isOn)} />;
}

When Effects ARE Appropriate

Data Fetching (with cleanup)

useEffect(() => {
  let ignore = false;
  fetchResults(query).then(json => {
    if (!ignore) setResults(json);  // Prevent race condition
  });
  return () => { ignore = true; };
}, [query]);

External Store Subscription

// ✅ Use dedicated hook
const isOnline = useSyncExternalStore(
  callback => {
    window.addEventListener('online', callback);
    window.addEventListener('offline', callback);
    return () => {
      window.removeEventListener('online', callback);
      window.removeEventListener('offline', callback);
    };
  },
  () => navigator.onLine,  // Client getter
  () => true               // Server getter
);

App Initialization

// ✅ Module-level, not in Effect
if (typeof window !== 'undefined') {
  checkAuthToken();
  loadDataFromLocalStorage();
}

Key Principles

  1. Calculate during render - Derived values don't need state or Effects
  2. Events belong in handlers - User interactions go in event handlers, not Effects
  3. Single render pass - Update multiple state variables in one event handler
  4. Use specialized hooks - useMemo, useSyncExternalStore over Effects
  5. Always cleanup async - Prevent race conditions with ignore flags
  6. Lift state when sharing - Parent component owns shared state

For detailed examples and edge cases, see references/patterns.md.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Security

Skill Safe Install

L0 级技能安全安装流程。触发“安装技能/安全安装/审查权限”时,强制执行 Step0-5(查重→检索→审查→沙箱→正式安装→白名单)。

Registry SourceRecently Updated
3740Profile unavailable
Security

Skill Hunter

Find, evaluate, and install ClawHub skills. Semantic search across 10,000+ skills, security vetting before install, side-by-side comparison. The skill that m...

Registry SourceRecently Updated
5152Profile unavailable
Security

audit-website

Audit websites for SEO, performance, security, technical, content, and 15 other issue cateories with 230+ rules using the squirrelscan CLI. Returns LLM-optimized reports with health scores, broken links, meta tag analysis, and actionable recommendations. Use to discover and asses website or webapp issues and health.

Repository Source
Security

better-auth-security-best-practices

No summary provided by upstream source.

Repository SourceNeeds Review