# No Use Effect

Avoid direct React `useEffect` usage when writing or reviewing React components and hooks.

- Repository: https://github.com/fastrepl/anarlog (9738 stars)
- Category: AI and agents
- License: MIT
- Last updated: 2026-11-01
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add fastrepl/anarlog --skill no-use-effect -g -a claude-code -y`
Codex: `npx skills add fastrepl/anarlog --skill no-use-effect -g -a codex -y`
Cursor: `npx skills add fastrepl/anarlog --skill no-use-effect -g -a cursor -y`
Gemini CLI: `npx skills add fastrepl/anarlog --skill no-use-effect -g -a gemini-cli -y`
Claude Code plugin marketplace: `/plugin marketplace add fastrepl/anarlog`

## Description

Avoid direct React `useEffect` usage when writing or reviewing React components and hooks. Use this skill when creating new React code, refactoring existing `useEffect` calls, reviewing PRs that introduce `useEffect`, or when an agent reaches for `useEffect` as a default. Replace effects with derived state, query or mutation libraries, event handlers, `useMountEffect` for mount-only external sync, or `key`-based remounts.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# No useEffect

Never call `useEffect` directly unless the work is a true mount-only sync with an external system and no simpler pattern fits. Prefer a render-time computation, a query or mutation hook, an event handler, or a remount boundary instead.

## Workflow

1. Classify why the effect exists.
2. Replace it with the narrowest pattern below.
3. Verify with the project's normal lint, typecheck, and tests.

## Replacement Patterns

### 1. Derive state, do not sync it

Replace `useEffect(() => setX(derive(y)), [y])` with inline computation or the project's existing memoization conventions.

```tsx
const filteredProducts = products.filter((product) => product.inStock);
```

Smell test: state only mirrors props or other state.

### 2. Use query or mutation libraries for async work

Replace fetch-in-effect code with the app's data layer.

```tsx
const productQuery = useQuery({
  queryKey: ["product", productId],
  queryFn: () => fetchProduct(productId),
});
```

Smell test: the effect fetches, awaits, retries, cancels, or writes async results into local state.

### 3. Use event handlers for user actions

Do the work where the action happens instead of setting a flag and reacting later.

```tsx
const handleLike = () => {
  postLike();
};
```

Smell test: state exists only to trigger an effect, then gets reset.

### 4. Use `useMountEffect` for mount-only external sync

Use this only for work that is naturally "set up on mount, clean up on unmount": DOM integration, subscriptions, third-party widgets, and stable singleton bindings.

If the project already has a `useMountEffect`, use it. If not, add a small wrapper:

```tsx
import { useEffect } from "react";

export function useMountEffect(effect: () => void | (() => void)) {
  useEffect(effect, []);
}
```

Prefer changing component structure so the component only mounts once preconditions are satisfied.

Smell test: the effect is a one-time setup or teardown for something outside React.

The rest: https://github.com/fastrepl/anarlog/blob/HEAD/.agents/skills/no-use-effect/SKILL.md
