.cursor/skills/react-useeffect/SKILL.md
React useEffect best practices from official docs and naming discipline. Use when writing/reviewing useEffect, naming effects, useState for derived values, data fetching, or state synchronization. Strong recommendation to name every effect; teaches when NOT to use Effect and better alternatives.
npx skillsauth add FixMyBerlin/tilda-geo react-useeffectInstall 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.
Effects are an escape hatch from React. They let you synchronize with external systems. If there is no external system involved, you usually should not use an Effect.
Always pass a named function expression to useEffect, not an anonymous arrow. Treat this as the default style for new and edited code.
// Avoid for useEffect (anonymous — hard to skim and debug)
useEffect(() => {
document.title = `${count} items`;
}, [count]);
// Prefer — intent at the call site; named stacks in errors and DevTools
useEffect(function updateDocumentTitle() {
document.title = `${count} items`;
}, [count]);
Equivalent at a glance: useEffect(function connectToInventoryWebSocket() { ... }, [warehouseId]) vs useEffect(() => { ... }, [warehouseId]).
Why this matters
at connectToInventoryWebSocket instead of at (anonymous); React DevTools shows the same.Cleanup: When teardown is non-trivial, prefer a named cleanup for symmetry and stack clarity:
useEffect(function pollServerForUpdates() {
const intervalId = setInterval(/* ... */, 5000);
return function stopPollingServer() {
clearInterval(intervalId);
};
}, [serverId]);
Other hooks: The same readability applies wherever you pass a function you did not name — useCallback, useMemo factories, reducers — but useEffect benefits most because timing, dependencies, and cleanup are the hardest to infer.
Custom hooks: Still name effects inside the hook; encapsulation does not replace named effects when a hook contains several.
Naming is a design review at the keyboard. Use it together with Anti-Patterns (examples and fixes live there — avoid duplicating that material here).
| Signal | Meaning | Where to look |
|--------|---------|----------------|
| Name needs “and” / “also” | Unrelated concerns in one effect | Split into separate effects, each with one name |
| Name like syncDerivedValue, updateStateFromState, setXBasedOnY | Likely derived state or state-to-state sync | Anti-Patterns §1 — derive during render; useMemo if expensive |
| Name like notifyParentOfChange, reportStateToParent | Parent updates driven by child state | Anti-Patterns §6–7 — event handler, lift data, or controlled pattern |
| Name like resetFormOnSubmitFlag | User intent expressed via state hop | Anti-Patterns §4 — handle in the event handler |
| Clear, external verbs: connectTo…, subscribeTo…, initialize…, synchronize… (with browser, network, map SDK, etc.) | Often legitimate Effect territory | Still name them; add cleanup when needed |
If the honest name sounds like internal React bookkeeping, the code often belongs in render, an event handler, or a different pattern — see the linked sections.
| Situation | DON'T | DO |
|-----------|-------|-----|
| Derived state from props/state | useState + useEffect | Calculate during render |
| Expensive calculations | useEffect to cache | useMemo |
| Reset state on prop change | useEffect with setState | key prop |
| User event responses | useEffect watching state | Event handler directly |
| Notify parent of changes | useEffect calling onChange | Call in event handler |
| Fetch data | useEffect without cleanup | useEffect with cleanup OR framework |
useSyncExternalStore when it fits)const x = f(a, b))Details and fixes: Anti-Patterns. Alternatives: Better Alternatives.
Need to respond to something?
├── User interaction (click, submit, drag)?
│ └── Use EVENT HANDLER
├── Component appeared on screen?
│ └── Use EFFECT (external sync, analytics)
├── Props/state changed and need derived value?
│ └── CALCULATE DURING RENDER
│ └── Expensive? Use useMemo
└── Need to reset state when prop changes?
└── Use KEY PROP on component
tools
Build type-safe global state in React with Zustand. Supports TypeScript, persist middleware, devtools, slices pattern, and Next.js SSR with hydration handling. Prevents 6 documented errors. Use when setting up React state, migrating from Redux/Context, or troubleshooting hydration errors, TypeScript inference, infinite render loops, or persist race conditions.
testing
Run local Docker processing in reference then fixed diffing mode to validate Lua/SQL topic changes via public.*_diff tables. From app/, use `processing-generate-command` to print a copy-paste shell line (interactive Clack on a TTY); agents/CI pass the full non-interactive flag set (see --help). Triggers on processing verification, bbox/topic-limited runs, or diff regression after editing processing/topics.
development
Migrate Next.js apps to TanStack Start. Covers setup (Vinxi/Vite), data handling with route loaders, converting Server Actions to Server Functions, API routes, and optional Server Component patterns. Use when migrating from Next.js to TanStack Start, setting up TanStack Start, or refactoring server actions, getServerSideProps, getStaticProps, or API routes.
development
This skill should be used when building React components with TypeScript, typing hooks, handling events, or when React TypeScript, React 19, Server Components are mentioned. Covers type-safe patterns for React 18-19 including generic components, proper event typing, and routing integration (TanStack Router, React Router).