skills/you-might-not-need-an-effect/SKILL.md
Refactor React components to remove unnecessary useEffect usage. Use when reviewing or rewriting React code that derives state from props, transforms data for rendering, mirrors values between components, resets state on prop change, performs event-specific work inside effects, subscribes to external stores, or needs guidance on when useEffect is actually appropriate.
npx skillsauth add cenjie/skills you-might-not-need-an-effectInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Identify whether each useEffect synchronizes with an external system. Keep the effect only when it coordinates React with something outside React such as the network, browser APIs, timers, subscriptions, imperative widgets, or analytics tied to display.
For every candidate effect, classify it before editing:
Apply the smallest replacement that preserves behavior:
useMemo only for expensive pure calculations.key.useSyncExternalStore for external subscriptions.useEffect, the state it reads, and the state it writes.key reset, or a better state shape.useSyncExternalStore when practical.Remove state like fullName, filtered arrays, JSX fragments, counters, or selected objects when they can be computed from existing props/state on every render.
Prefer:
const fullName = firstName + ' ' + lastName;
const activeTodos = todos.filter(todo => !todo.completed);
const selection = items.find(item => item.id === selectedId) ?? null;
If derivation is expensive and inputs are stable, wrap the calculation in useMemo. Do not use an effect plus state as a cache.
Move POST requests, notifications, parent callbacks, and multi-state updates into the event handler or a helper called by that handler.
When switching between conceptual entities like userId, contact.id, or threadId, split the component and pass the identity as key to the inner stateful component.
If only part of local state must change after props change and you cannot avoid local state entirely, prefer changing state during render with a guarded previous-value check over using an effect. Use this sparingly and only for the same component's state.
Replace patterns like manual addEventListener plus useState with useSyncExternalStore when subscribing to mutable external data.
Fetching can stay in an effect when results must track visible inputs such as query/page. Add cleanup to ignore stale responses. Prefer framework loaders or shared data hooks when available.
useMemo by default unless computation cost or re-render boundaries justify it.When using this skill:
development
Launch both thermo-nuclear review subagents in parallel, then synthesize their findings. Use for thermos, double thermo review, or combined bug/security and code-quality branch audits.
development
Comprehensive security and correctness audit of a branch's changes. Use for thermo nuclear, thermonuclear, or deep review requests, or branch/PR diff audits focused on bugs, breaking changes, security issues, devex regressions, and feature-gate leaks.
development
Run an extremely strict maintainability review for abstraction quality, giant files, and spaghetti-condition growth. Use for a thermo-nuclear code quality review, thermonuclear review, deep code quality audit, or especially harsh maintainability review.
development
Use for custom storefronts requiring direct GraphQL queries/mutations for data fetching and cart operations. Choose this when you need full control over data fetching and rendering your own UI. NOT for Web Components - if the prompt mentions HTML tags like <shopify-store>, <shopify-cart>, use storefront-web-components instead.