Agent skill

Conventions Use Effect

by stella in stella/stella

Apply when writing or reviewing React effects in apps/web. An agent skill from stella/stella.

Apache-2.0Auto-check passed

Install Conventions Use Effect

skills CLI
$ npx skills add stella/stella --skill conventions-use-effect -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install stella/stella conventions-use-effect --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/stella/stella.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/conventions-use-effect .claude/skills/conventions-use-effect && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
conventions-use-effect
GitHub stars
258
Token cost
~2.8k tokens
SKILL.md length
1,226 words
Files
1
Skills in repo
24
Repo updated
First seen
Licence
Apache-2.0

At a glance

Apply when writing or reviewing React effects in apps/web. An agent skill from stella/stella.

  • Works in 5 steps: Can it be derived during render? Then… → Is it data fetching? Use TanStack Query.… → Does it happen in response to a user… → …
  • SKILL.md covers Decision order, Rule 1 — derive state, do not…, Rule 2 — data-fetching… and Rule 3 — event handlers, not…, plus 8 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Conventions Use Effect is an agent skill from stella/stella. Apply when writing or reviewing React effects in apps/web. Direct useEffect is banned; use the sanctioned wrappers or a better primitive.

Its SKILL.md is about 2.8k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It works with React. The repository describes itself as: Open-source legal workspace. The licence is Apache-2.0.

Example prompts

  • “/conventions-use-effect”

Workflow steps

5 steps, taken from the first numbered list in SKILL.md.

  1. Can it be derived during render? Then derive it. (Rule 1)
  2. Is it data fetching? Use TanStack Query. (Rule 2)
  3. Does it happen in response to a user action? Do it in the event handler. (Rule 3)
  4. Does it reset state when an id/prop changes? Remount with key. (Rule 5)
  5. Is it genuine external-system synchronization? Use useMountEffect

What it can do on your machine

Read from SKILL.md and the folder at commit 269655d. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are typescript).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • react.dev

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Conventions Use Effect loads about 2.8k tokens when it runs. Until then it costs about 40 tokens; SKILL.md has 1,226 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~40
When it runs · the whole SKILL.md, loaded when a task matches
~2.8k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from stella/stella at commit 269655d, republished under its Apache-2.0 licence (© stella). 1,226 words, ~2,770 tokens.

Download SKILL.mdSave it as .claude/skills/conventions-use-effect/SKILL.md (or your agent's skills folder).
name
conventions-use-effect
description
Apply when writing or reviewing React effects in apps/web. Direct useEffect is banned; use the sanctioned wrappers or a better primitive.

useEffect Conventions

Apply when writing or reviewing React code in apps/web.

Direct useEffect is banned in apps/web/src and enforced by the no-raw-use-effect lint rule. Most effects compensate for primitives React already gives you; the rest are external-system synchronization that must go through a named wrapper so intent is explicit and greppable. React Compiler is enabled tree-wide, so "derive during render" costs nothing.

Background: React's own guide, You Might Not Need an Effect.

Decision order

Before reaching for any effect, walk this list top to bottom and stop at the first match:

  1. Can it be derived during render? Then derive it. (Rule 1)
  2. Is it data fetching? Use TanStack Query. (Rule 2)
  3. Does it happen in response to a user action? Do it in the event handler. (Rule 3)
  4. Does it reset state when an id/prop changes? Remount with key. (Rule 5)
  5. Is it genuine external-system synchronization? Use useMountEffect or useExternalSyncEffect. (Rule 4)

If none match, you almost certainly do not need an effect.

Rule 1 — derive state, do not sync it

tsx
// ❌ extra render + loop hazard
const [filtered, setFiltered] = useState([]);
useEffect(() => setFiltered(products.filter((p) => p.inStock)), [products]);

// ✅ compute inline (React Compiler memoizes it)
const filtered = products.filter((p) => p.inStock);

Smell: useEffect(() => setX(deriveFrom(y)), [y]), or state that only mirrors other state/props.

Rule 2 — data-fetching library, not an effect

tsx
// ❌ race conditions, hand-rolled caching
useEffect(() => { fetchProduct(id).then(setProduct); }, [id]);

// ✅ cancellation/caching/staleness handled for you
const { data: product } = useQuery(productOptions(id));

Smell: an effect that does fetch(...) then setState(...), or re-implements retries/cancellation/staleness.

Rule 3 — event handlers, not effects

tsx
// ❌ effect as an action relay
useEffect(() => { if (liked) { postLike(); setLiked(false); } }, [liked]);

// ✅ do the work where the event happens
<button onClick={() => postLike()}>Like</button>

Smell: state used as a flag so an effect can run the real action ("set flag → effect runs → reset flag").

Rule 5 — reset with key, not dependency choreography

tsx
// ✅ a new id gives a brand-new instance; mount logic runs once, cleanly
<Editor key={documentId} documentId={documentId} />

Smell: an effect whose only job is to reset local state when an id changes.

Rule 4 — the two sanctioned wrappers

Both live in @/hooks/use-effect and are the only place a raw useEffect may be called.

useMountEffect(effect)

Setup/teardown on mount, once. For DOM imperatives (focus, scroll), third-party widget lifecycles, and browser-API subscriptions.

tsx
useMountEffect(() => {
  const controller = new AbortController();
  window.addEventListener("resize", onResize, { signal: controller.signal });
  return () => controller.abort();
});
useExternalSyncEffect(effect, deps)

Push a changing React value into an external system when it changes. The only sanctioned dependency-array effect. Every call must be an external-system sync — never derived state, an event relay, or a fetch.

tsx
// Push zoom into the imperative folio editor whenever it changes.
useExternalSyncEffect(() => editorRef.current?.setZoom(zoom), [zoom]);

When the external lifecycle is "set up once per DOM node," use a callback ref over an effect (it ties setup/teardown to the node, not to a render) — see the ResizeObserver/fit-zoom pattern in the docx viewers. This is the canonical shape for ResizeObserver, IntersectionObserver, DOM listeners, and imperative widgets whose lifecycle belongs to a specific element. Keep an effect only when the component does not own the node/ref API yet, or when the work is truly "push a changing React value into an already-attached external system."

useLatestCallback(fn) — latest-values callbacks for external systems

When a callback must be handed to something that outlives the render that created it (a listener registered inside useExternalSyncEffect, a query context object, an imperative editor/runtime bridge) and it should read the latest committed state without re-triggering the subscription, wrap it in useLatestCallback from @/hooks/use-latest-callback: stable identity, always invokes the latest closure, creates no reactivity.

Do not reach for React's useEffectEvent: its contract restricts calls to raw useEffect bodies of the same component, which the wrapper-only policy above makes unsatisfiable — react-hooks/rules-of-hooks flags every such use. useLatestCallback has the same semantics minus that restriction. Two contract points: never call the result during render, and list it in the useExternalSyncEffect deps array when used there (its identity is stable, so it never causes re-runs; the entry only satisfies exhaustive-deps).

Feedback loops on imperative-editor boundaries

Any state write triggered by an external editor or subscription callback (tiptap onUpdate, folio dispatch, store subscriptions) must be a no-op when nothing semantically changed. Otherwise write → re-render → editor re-emits → write sustains itself until React throws "Maximum update depth exceeded"; the loop typically only ignites under a re-render storm (e.g. response streaming), so it survives casual testing.

The no-op guard's comparator must be identity-based, not structural. Track the exact object you last handed to (or received from) the editor — a WeakSet/ref identity latch, as in shouldApplyStoredDraftToEditor in chat-editor-provider.tsx. JSON.stringify or shallow equality is not sufficient on an editor boundary: imperative editors serialize non-canonically (getJSON/setContent round-trips are not idempotent — attrs appear, empty content: [] comes and goes), so a semantic no-op reads as a change and the loop walks straight through a structural guard. Do not "simplify" an identity latch into a structural comparison.

Show full SKILL.md (533 more words)Show less

Context values: never fold volatile state into a stable API

A context value memoized as a stable API must not carry any field that changes at runtime (version counters, monotonic bump values, activeX keys). One volatile field gives the whole context a new identity on every bump, so every consumer re-renders and its registration effects re-fire — and if registering bumps the counter, that is a self-sustaining loop (damped normally, explosive under load). Split volatile values into their own context, or expose them via ref + subscribe; the stable-API context's fields must be referentially permanent for the provider's lifetime.

useLayoutEffect

Not covered by the ban (it has legitimate pre-paint imperative uses), but the same decision order applies. Reach for it only when a measurement or imperative write must happen before the browser paints.

Stale async responses

An in-flight async call that resolves after the component has moved on — a route navigation, an entity/id switch, or a newer request superseding an older one — can still land its result after nothing should be listening anymore. Left unguarded, the stale response applies over a fresher one and the UI shows wrong data. Two situations, two different fixes.

TanStack Query: thread the signal

useQuery/useInfiniteQuery/queryOptions pass an AbortSignal to every queryFn via its first argument. A queryFn that never destructures it never cancels a superseded call. Thread it into both fetch and Eden calls:

tsx
queryFn: async ({ signal }) => {
  const response = await api.things.get({ fetch: { signal } });
  ...
};

Combine it with a call-specific timeout via AbortSignal.any([signal, AbortSignal.timeout(ms)]) when the call also needs an upper bound independent of query cancellation (see fetchPrintPdf in peek-pdf-viewer.tsx). Enforced in apps/web/src by the require-query-signal lint rule, scoped to queryFn bodies that call fetch/Eden directly.

Hand-rolled async + setState: the render-time identity latch

Manually paged/accumulated state — seeded from a query's data and then extended by imperative "load older" calls — has no queryFn for TanStack to cancel, so it needs its own guard.

The fix is a request-generation identity latch: a ref holding the current "generation" (the query's data object identity, or an equivalent runtime instance), written synchronously during render rather than in a passive effect — that closes the commit→effect window a response could otherwise resolve into undetected. The async callback captures the ref before starting the fetch and compares it again after the await resolves; a mismatch means the page/entity changed underneath the request, so the response is discarded instead of applied:

tsx
const seededDataRef = useRef(data);
if (data !== undefined && seededData !== data) {
  setSeededData(data);
  /* oxlint-disable react/refs -- render-time ref write closes the commit→effect race window for the stale-response guard */
  seededDataRef.current = data;
  /* oxlint-enable react/refs */
}

const loadOlder = useCallback(async () => {
  const requestedData = seededDataRef.current;
  const older = await fetchOlderVersions(/* ... */);
  if (seededDataRef.current !== requestedData) {
    return; // superseded — a refetch or entity switch reseeded the page
  }
  setAccumulated((current) => [...current, ...older.versions]);
}, [/* ... */]);

In-repo exemplars: apps/web/src/components/inspector/versions-facet.tsx (seededDataRef) and apps/web/src/features/chat/hooks/use-chat-session.ts (seededChatRef). This is a narrow, explicitly allowlisted exception to no-ref-mirror (not a general recipe to reach for) — useLatestCallback (and React's useEffectEvent) do not protect this window because their updates are effect-timed while the write must happen during render. A new call site needs its own justified entry in that rule's allowedFiles in oxlint.config.ts.

Escape hatch

For a genuine effect that does not fit either wrapper (or that is pending migration), suppress at the call site with a reason — suppression-hygiene requires the description:

tsx
// oxlint-disable-next-line no-raw-use-effect/no-raw-use-effect -- <why a wrapper does not fit>
useEffect(/* ... */);

Prefer fixing over suppressing. A bare disable with no reason is itself a lint error.

Scope

Enforced in apps/web/src. The folio editor ships as the external @stll/folio-react dependency and stays outside that scope: it is an inherently imperative editor where most effects are legitimate external-system sync, so the rule would generate suppression noise and fight every upstream merge for little benefit.

© stella, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .agents/skills/conventions-use-effect of stella/stella.

Open the folder on GitHubat commit 269655d

Compare with similar skills

Conventions Use Effect next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Conventions Use Effect compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Conventions Use Effect this skillstella/stella258—~2.8kAutomated safety check: PassApache-2.0
Web Artifacts Builderanthropics/skills180k41 repos~769Automated safety check: PassApache-2.0
Vercel Composition Patternssupabase/supabase111k59 repos~726Automated safety check: PassMIT
React Doctormakeplane/plane61k12 repos~657Automated safety check: PassAGPL-3.0
React Router Developmentremix-run/react-router57k1 repos~1.5kAutomated safety check: PassMIT
React UI State PatternsChrisWiles/claude-code-showcase6.1k8 repos~1.6kAutomated safety check: PassNone

Similar skills

  • Web Artifacts Builder

    anthropics/skills

    Official

    Builds multi-component claude.ai HTML artifacts as a small React, TypeScript and Tailwind project, then bundles it into one shareable HTML file.

    180k GitHub starsUsed in 41 repos~769 tokens
    Frontend & DesignAuto-check passed
  • Official

    React composition patterns that scale. An agent skill from supabase/supabase.

    111k GitHub starsUsed in 59 repos~726 tokens
    DevelopmentAuto-check passed
  • React Doctor

    makeplane/plane

    Scans React code for lint, accessibility, bundle size and architecture issues, reports a health score and checks that changes do not lower it.

    61k GitHub starsUsed in 12 repos~657 tokens
    Frontend & DesignAuto-check passed
  • React Router Development

    remix-run/react-router

    Guides work on React Router apps by first identifying whether the app uses Framework, Data or Declarative mode, then loading the matching reference and the installed package docs.

    57k GitHub starsUsed in 1 repo~1.5k tokens
    Frontend & DesignAuto-check passed
  • React UI State Patterns

    ChrisWiles/claude-code-showcase

    Sets patterns for React interfaces: when to show loading spinners or skeletons, how to surface errors, how to disable buttons during async work and how to handle empty lists.

    6.1k GitHub starsUsed in 8 repos~1.6k tokens
    Frontend & DesignAuto-check passed
  • Stitch to Remotion Walkthrough Videos

    google-labs-code/stitch-skills

    Official

    Builds walkthrough videos from Stitch design projects using Remotion, with transitions, zoom effects and text overlays on each screen.

    8.4k GitHub starsUsed in 6 repos~3.2k tokens
    Media & CreativeAuto-check: notes

More from stella/stella

All 24 skills in this repo
  • Plan

    stella/stella

    Create a concise, evidence-backed implementation plan in the repository planning area when the user explicitly asks for a plan.

    258 GitHub stars~917 tokensUpdated today
    Auto-check passed
  • Answer From Sources

    stella/stella

    Answers data-protection (GDPR) questions grounded in the regulation and supervisory guidance, with a citation for every claim.

    258 GitHub stars~735 tokensUpdated today
    Auto-check passed
  • Check Against Rules

    stella/stella

    Reviews a non-disclosure agreement against the firm's NDA checklist and reports findings with citations.

    258 GitHub stars~856 tokensUpdated today
    Auto-check passed
  • Intake To Draft

    stella/stella

    Collects the facts of an unpaid invoice, then drafts a payment demand letter.

    258 GitHub stars~537 tokensUpdated today
    Auto-check passed
  • Conventions Perf

    stella/stella

    Apply when a performance-guard check (network baseline, bundle baseline, DB query count, loader-prefetch lint, RC bailouts) fails or when touching a hot route/endpoint.

    258 GitHub stars~2.9k tokensUpdated today
    Auto-check passed
  • Dev

    stella/stella

    Start, drive and measure the local stack. An agent skill from stella/stella.

    258 GitHub stars~1.4k tokensUpdated today
    Auto-check passed

Works with

Questions about Conventions Use Effect

What does Conventions Use Effect do?

Apply when writing or reviewing React effects in apps/web. An agent skill from stella/stella. Conventions Use Effect is an agent skill from stella/stella. Apply when writing or reviewing React effects in apps/web.

How do I install Conventions Use Effect in Claude Code?

Run `npx skills add stella/stella --skill conventions-use-effect -a claude-code`. Or copy the skill folder (.agents/skills/conventions-use-effect in stella/stella) into .claude/skills/conventions-use-effect in your project. Claude Code loads it when a task matches its description.

How do I install Conventions Use Effect in Codex?

Run `npx skills add stella/stella --skill conventions-use-effect -a codex`. Or copy the skill folder (.agents/skills/conventions-use-effect in stella/stella) into .agents/skills/conventions-use-effect in your project. Codex loads it when a task matches its description.

Can I use Conventions Use Effect in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add stella/stella --skill conventions-use-effect -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/conventions-use-effect, .gemini/skills/conventions-use-effect, .github/skills/conventions-use-effect and .opencode/skills/conventions-use-effect in your project.

What does Conventions Use Effect need to run?

SKILL.md names no scripts, command-line tools or credentials: Conventions Use Effect is instructions for the agent only.

Does Conventions Use Effect access the network?

SKILL.md names 1 domain. As links in the text: react.dev. This is read from the text; nothing was executed.

Is Conventions Use Effect safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Conventions Use Effect use?

Conventions Use Effect is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Conventions Use Effect use?

About 2.8k tokens (SKILL.md is roughly 11k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Conventions Use Effect?

Skills that share tags, products or a category with Conventions Use Effect: Web Artifacts Builder (anthropics/skills, 180k stars), Vercel Composition Patterns (supabase/supabase, 111k stars), React Doctor (makeplane/plane, 61k stars) and React Router Development (remix-run/react-router, 57k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Conventions Use Effect?

stella (a GitHub organization) maintains it in stella/stella, which has 258 GitHub stars. The repository holds 24 skills in this directory. The repository was last updated on October 8, 2026.

Source: stella/stella on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.