Our review
Guides writing React components by avoiding unnecessary useEffect calls, using alternatives like computed values during render, event handlers, and key props.
Strengths
- Reduces unnecessary re-renders and bugs
- Promotes a cleaner data flow
- Teaches a mental model for when useEffect is truly needed
- Provides concrete anti-pattern examples and fixes
Limitations
- Does not cover advanced usages like custom hooks for external systems
- May not address complex state management patterns
- Focuses on React, not other frameworks
Use when writing or reviewing React components to eliminate unnecessary effects and improve performance.
Do not use when working with external system integrations that genuinely require useEffect, or when dealing with legacy code that cannot be refactored easily.
Security analysis
SafeThe skill is a purely instructional guide for writing React components without unnecessary useEffect. It contains no executable code, no tool invocations, and no instructions for destructive or exfiltrating actions. There is no risk of misuse.
No concerns found
Examples
I have a React component that uses useEffect to filter a list when props change. How can I refactor it to avoid the effect?In this component, I'm using useEffect to call onSelect whenever selectedId changes. How can I move this to the event handler instead?I have a form component that needs to reset all its state when the userId prop changes. Currently I'm using useEffect. What's a better approach?name: writing-react-effects description: Writes React components without unnecessary useEffect. Use when creating/reviewing React components, refactoring effects, or when code uses useEffect to transform data or handle events. disable-model-invocation: false
Writing React Effects Skill
Guides writing React components that avoid unnecessary useEffect calls.
Core Principle
Effects are an escape hatch for synchronizing with external systems (network, DOM, third-party widgets). If there's no external system, you don't need an Effect.
Decision Flowchart
When you see or write useEffect, ask:
Is this synchronizing with an EXTERNAL system?
├─ YES → useEffect is appropriate
│ Examples: WebSocket, browser API subscription, third-party library
│
└─ NO → Don't use useEffect. Use alternatives:
│
├─ Transforming data for render?
│ → Calculate during render (inline or useMemo)
│
├─ Handling user event?
│ → Move logic to event handler
│
├─ Expensive calculation?
│ → useMemo (not useEffect + setState)
│
├─ Resetting ALL state when prop changes?
│ → Pass different `key` to component
│
├─ Adjusting SOME state when prop changes?
│ → Calculate during render or rethink data model
│
├─ Subscribing to external store?
│ → useSyncExternalStore
│
└─ Fetching data?
→ Framework data fetching or custom hook with cleanup
Anti-Patterns to Detect and Fix
| Anti-Pattern | Problem | Alternative |
| --------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------ |
| useEffect + setState from props/state | Causes extra re-render | Compute during render |
| useEffect to filter/sort/transform data | Unnecessary effect cycle | Derive inline or useMemo |
| useEffect for click/submit handlers | Loses event context | Event handler |
| useEffect to notify parent on state change | Breaks unidirectional data flow | Call parent callback in same event handler |
| useEffect with empty deps for one-time init | Runs twice in dev (Strict Mode); conflates app init with mount | Module-level code or didInit ref flag |
| useEffect for browser subscriptions | Error-prone manual cleanup | useSyncExternalStore |
| useEffect + setState for derived state | Double render, stale intermediate state | Compute value directly during render |
When useEffect IS Appropriate
- Syncing with external systems (WebSocket connections, third-party widgets, browser APIs)
- Setting up and cleaning up subscriptions
- Fetching data based on current props (always include cleanup to handle race conditions)
- Measuring or imperatively mutating DOM elements after render
- Integrating with non-React code (jQuery plugins, analytics SDKs, etc.)
Common Refactoring Patterns
Derived state → compute during render
// ❌ Bad
const [filtered, setFiltered] = useState([]);
useEffect(() => {
setFiltered(items.filter((i) => i.active));
}, [items]);
// ✅ Good
const filtered = items.filter((i) => i.active);
// or with useMemo for expensive operations
const filtered = useMemo(() => items.filter((i) => i.active), [items]);
Notify parent → call in event handler
// ❌ Bad
useEffect(() => {
onSelect(selectedId);
}, [selectedId]);
// ✅ Good
function handleClick(id) {
setSelectedId(id);
onSelect(id);
}
Reset state on prop change → key prop
// ❌ Bad
useEffect(() => {
setComment("");
}, [userId]);
// ✅ Good — key remounts the component, resetting all state
<ProfileForm key={userId} userId={userId} />;
Data fetching → custom hook with cleanup
// ❌ Bad — no cleanup, race conditions possible
useEffect(() => {
fetch(`/api/user/${id}`)
.then((r) => r.json())
.then(setUser);
}, [id]);
// ✅ Good — cleanup prevents stale responses
useEffect(() => {
let cancelled = false;
fetch(`/api/user/${id}`)
.then((r) => r.json())
.then((data) => {
if (!cancelled) setUser(data);
});
return () => {
cancelled = true;
};
}, [id]);
// ✅ Even better — use a data-fetching library (React Query, SWR, TanStack Query)
const { data: user } = useQuery({
queryKey: ["user", id],
queryFn: () => fetchUser(id),
});
Instructions for Claude
When this skill is invoked:
- Identify every
useEffectcall in the provided code - Apply the decision flowchart to each effect individually
- Flag anti-patterns from the table above with a clear explanation of the problem
- Provide refactored code using the appropriate alternative for each case
- Leave legitimate effects untouched — only remove effects that don't belong
- When writing new components, never reach for
useEffectunless the flowchart confirms it's appropriate
Prioritize correctness over cleverness. A derived value computed inline is always clearer than an effect that syncs it into state.
Next.js App Router Expert
Development
A skill that turns Claude into a Next.js App Router expert.
README Generator
Development
Creates professional and comprehensive README.md files for your projects.
API Documentation Writer
Development
Generates comprehensive API documentation in OpenAPI/Swagger format.