Files
5chan/.codex/skills/you-might-not-need-an-effect/SKILL.md
T
Tommaso CasaburiandGitHub a92b185a66 chore(ai-workflow): track repo-managed review tooling (#1046)
* chore(ai-workflow): track repo-managed review tooling

* fix(ai-workflow): remove repo-specific path assumptions

Make shared workflow hooks and APK testing guidance resolve paths from the repo and contributor environment so the tooling works for all contributors, not just one machine.
2026-03-10 15:49:15 +08:00

4.4 KiB

name, description, disable-model-invocation
name description disable-model-invocation
you-might-not-need-an-effect Analyze code for useEffect anti-patterns and refactor to simpler alternatives. Use when the user says "you might not need an effect", "check effects", "useEffect audit", or asks to review useEffect usage. true

You Might Not Need an Effect

Analyze code for useEffect anti-patterns and refactor to simpler, more correct alternatives.

Based on https://react.dev/learn/you-might-not-need-an-effect

Arguments

  • scope: what to analyze (default: uncommitted changes). Examples: diff to main, src/components/, whole codebase
  • fix: whether to apply fixes (default: true). Set to false to only propose changes.

Workflow

  1. Determine scope — get the relevant code:

    • Default: git diff for uncommitted changes
    • If a directory/file is specified, read those files
    • If "whole codebase": search all .tsx/.ts files for useEffect
  2. Scan for anti-patterns — check each useEffect against the patterns below

  3. Fix or propose — depending on the fix argument:

    • fix=true: apply the refactors, then verify with yarn build && yarn lint && yarn type-check
    • fix=false: list each anti-pattern found with a before/after code suggestion
  4. Report — summarize what was found and changed

Anti-Patterns to Catch

1. Deriving state during render (no effect needed)

If you're computing something from existing props or state, calculate it during render.

// ❌ Anti-pattern
const [fullName, setFullName] = useState('');
useEffect(() => {
  setFullName(firstName + ' ' + lastName);
}, [firstName, lastName]);

// ✅ Fix — derive during render
const fullName = firstName + ' ' + lastName;

2. Caching expensive calculations (useMemo, not useEffect)

// ❌ Anti-pattern
const [filtered, setFiltered] = useState([]);
useEffect(() => {
  setFiltered(items.filter(item => item.active));
}, [items]);

// ✅ Fix — calculate during render (useMemo only if profiling shows it's needed)
const filtered = items.filter(item => item.active);

3. Resetting state when props change (use key, not useEffect)

// ❌ Anti-pattern
useEffect(() => {
  setComment('');
}, [postCid]);

// ✅ Fix — use key on the component to reset state
<CommentForm key={postCid} />

4. Fetching data (use bitsocial-react-hooks, not useEffect)

This project uses bitsocial-react-hooks for all data fetching. Never use useEffect + fetch.

// ❌ Anti-pattern
const [comment, setComment] = useState(null);
useEffect(() => {
  fetchComment(cid).then(setComment);
}, [cid]);

// ✅ Fix — use the hook
const { state, ...comment } = useComment({ commentCid: cid });

5. Syncing with external stores (use Zustand, not useEffect)

// ❌ Anti-pattern
const [theme, setTheme] = useState('light');
useEffect(() => {
  const unsub = settingsStore.subscribe((s) => setTheme(s.theme));
  return unsub;
}, []);

// ✅ Fix — use the Zustand store directly
const theme = useSettingsStore((s) => s.theme);

6. Sending analytics / logging (move to event handlers)

// ❌ Anti-pattern — fires on every render, not on user action
useEffect(() => {
  logPageView(pageName);
}, [pageName]);

// ✅ Fix — call in the event handler or route change callback
const navigate = () => {
  logPageView(pageName);
  router.push(path);
};

7. Initializing global singletons (use module scope or lazy init)

// ❌ Anti-pattern
useEffect(() => {
  initializeAnalytics();
}, []);

// ✅ Fix — module-level init (runs once on import)
if (typeof window !== 'undefined') {
  initializeAnalytics();
}

Project-Specific Replacements

useEffect pattern Replace with
Fetch data useComment, useFeed, useSubplebbit, etc. from bitsocial-react-hooks
Sync shared state Zustand store in src/stores/
Derive values from state Calculate during render
Boolean loading/error flags state field from bitsocial-react-hooks, or state machine in Zustand

When useEffect IS Appropriate

Not every effect is wrong. Keep useEffect for:

  • Subscribing to browser APIs (resize, intersection observer, etc.) with proper cleanup
  • Synchronizing with non-React systems (third-party widgets, imperative DOM)
  • Running code on mount that genuinely has no hook equivalent