fixmyberlin/fixmyskills

react-dev

>- React 19 + TypeScript for FMC TanStack Start apps: typed components, events, generics, ref-as-prop, Compiler-first memoization, and useEffect discipline (naming, when not to use Effect, alternatives). Use when typing React components/hooks/events, or writing/reviewing useEffect, useEffectEvent, derived state, data-fetch effects, or oxlint React Compiler / Rules of React effect rules. Not for routing/server boundaries (see tanstack-start-* skills).

First seen Jun 5, 2026

Installation

$ npx skills add fixmyberlin/fixmyskills --skill react-dev

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from fixmyberlin/fixmyskills · top by installs.

npx skills add fixmyberlin/fixmyskills

Browse all from fixmyberlin/fixmyskills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

License LICENSE
Default branch main
Open issues 0
Status Active

Skill metadata

Parsed from SKILL.md frontmatter.

Version3.0.0

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 20,530 B
  • docs SUMMARY.md 468 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 56 installs

SKILL.md

LLM reference: react.dev/llms.txt · tanstack.com/llms.txt · Key effect page: You Might Not Need an Effect

React + TypeScript (FMC)

Type-safe React = compile-time guarantees. This skill covers TypeScript patterns agents often get wrong and useEffect discipline (naming, scope, when to skip). Routing and server I/O live in sibling skills (below).

When to use

  • Typing props, children, refs, event handlers
  • Generic/reusable components (Table<T>, discriminated unions)
  • React 19 APIs (use(), ref as prop) — typing only
  • Writing or reviewing useEffect, useEffectEvent, effect cleanup, derived state
  • Reviewing TS or effects in components under components/

Not here: route loaders, createServerFn, SSR, Zustand → see [Related skills](#related-skills).

FMC stack (required)

Requirement Rule
React 19 Target 19.x; no forwardRef / useFormState in new code
React Compiler Enabled in the app build — auto-memoization is the default
Lint Oxlint react plugin — native Compiler rules on by default, plus 'react/unsupported-syntax': 'error'; no eslint-plugin-react-hooks jsPlugin
Memoization Do not add useMemo / useCallback / memo by default; add only when profiling or a lint rule requires it
TanStack Start Server I/O and mutations → tanstack-start-conventions (this skill covers component typing only)
Data fetching Route loaders + React Query — not useEffect fetch (see tanstack-router-conventions)

Docs: React Compiler · Rules of React · Oxc React Compiler Support

Related skills

Topic Skill
Effects, naming, when not to use Effect react-dev
Routes, loaders, validateSearch tanstack-router-conventions
SSR, server functions, Start layout tanstack-start-conventions
Folder layout, thin routes (Start) tanstack-start-conventionsapp-structure.md
createServerFn, server mutations tanstack-start-conventions → [server-functions.md](../tanstack-start-conventions/references/server-functions.md)
Client stores zustand-state-management
URL state (prefer router search) tanstack-router-conventions
Semantic HTML (div/span leftovers) unslop-code → [semantic-html.md](../unslop-code/references/semantic-html.md)

Component props

Extend native elements with ComponentPropsWithoutRef:

type ButtonProps = {
  variant: 'primary' | 'secondary';
} & React.ComponentPropsWithoutRef<'button'>;

function Button({ variant, children, ...props }: ButtonProps) {
  return <button className={variant} {...props}>{children}</button>;
}

Children: React.ReactNode (renderable). Single element: React.ReactElement. Avoid JSX.Element for children.

Variant props — discriminated unions:

type ButtonProps =
  | { variant: 'link'; href: string }
  | { variant: 'button'; onClick: () => void };

function Button(props: ButtonProps) {
  if (props.variant === 'link') return <a href={props.href}>Link</a>;
  return <button onClick={props.onClick}>Button</button>;
}

More: Using TypeScript · [generic-components.md](examples/generic-components.md)

ref as prop (React 19)

Prefer ref as a normal prop — avoid new forwardRef:

type InputProps = {
  ref?: React.Ref<HTMLInputElement>;
  label: string;
} & React.ComponentPropsWithoutRef<'input'>;

function Input({ ref, label, ...props }: InputProps) {
  return (
    <div>
      <label>{label}</label>
      <input ref={ref} {...props} />
    </div>
  );
}

Details: [react-19-patterns.md](references/react-19-patterns.md) · Manipulating the DOM with Refs

Event handlers

Use specific event types so currentTarget is typed:

Event Type
Click React.MouseEvent<HTMLButtonElement>
Submit React.FormEvent<HTMLFormElement>
Input change React.ChangeEvent<HTMLInputElement>
Key down React.KeyboardEvent<HTMLInputElement>
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
  e.preventDefault()
  const data = new FormData(e.currentTarget)
}

Full table + generics: [event-handlers.md](references/event-handlers.md) · Responding to Events

Hooks (typing only)

Hook Typing note
useState Explicit type for null unions, empty arrays, unions: `useState<User \ null>(null)`
useRef DOM: useRef<HTMLInputElement>(null) + ?. — mutable box: useRef(0)
useReducer Discriminated union for action
useContext `createContext<T \ null>(null)` + throw in custom hook
Custom hook tuples return [value, toggle] as const

Do not document useCallback/useMemo defaults here — Compiler handles memoization. Imperative handles / external store: [hooks.md](references/hooks.md).

useEffect — naming, scope, and when to skip

Effects are an escape hatch from React. They synchronize with external systems. If there is no external system involved, you usually should not use an Effect.

Name every useEffect (strong recommendation)

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],
)

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]);

The same readability applies to useCallback, useMemo factories, and reducers — but useEffect benefits most because timing, dependencies, and cleanup are the hardest to infer. Custom hooks: still name effects inside the hook.

Indicators from naming (what to do next)

Naming is a design review at the keyboard. Use it with [Anti-Patterns](references/anti-patterns.md) (examples and fixes live there).

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](references/anti-patterns.md#1-redundant-state-for-derived-values) — derive during render; useMemo if expensive
Name like notifyParentOfChange, reportStateToParent Parent updates driven by child state [Anti-Patterns §6–7](references/anti-patterns.md#6-notifying-parent-via-effect) — event handler, lift data, or controlled pattern
Name like resetFormOnSubmitFlag User intent expressed via state hop [Anti-Patterns §4](references/anti-patterns.md#4-event-specific-logic-in-effect) — handle in the event handler
Name like persistOnClose, syncWhenClosed, saveDraftOnDismiss Side effect on dismiss/open UI state [Anti-Patterns §4](references/anti-patterns.md#persist-or-sync-on-gesture--not-on-isopen--transition-flags) — handler, not Effect on isOpen
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.

Quick reference

Situation DON'T DO
Derived state from props/state useState + useEffect Calculate during render
Expensive calculations useEffect to cache Compute in render; useMemo only if needed (often unnecessary with React Compiler)
Reset state on prop change useEffect with setState key prop
User event responses useEffect watching state Event handler directly
Persist/sync on dismiss useEffect on isOpen Dismiss handler (or onCloseComplete)
Notify parent of changes useEffect calling onChange Call in event handler
Fetch data useEffect without cleanup useEffect with cleanup OR framework (loaders/Query)

When you DO need Effects

  • Synchronizing with external systems (non-React widgets, browser APIs, map SDKs)
  • Subscriptions to external stores (useSyncExternalStore when it fits)
  • Analytics/logging tied to display
  • Data fetching with proper cleanup when framework fetch is not available

Strict Mode (dev): Effects run setup twice on mount to surface missing cleanup. Add teardown for subscriptions, timers, and fetches — see [Anti-Patterns §8–9](references/anti-patterns.md#8-fetching-without-cleanup-race-condition).

Effects and React Compiler / ESLint

  • Render work: Prefer deriving values during render. With Compiler enabled (FMC default), skip manual useMemo unless profiling shows a need.
  • Effects: Compiler does not replace Effects for external synchronization. Changed memoization can change when effects re-run — fix effect design (deps, splits, useEffectEvent) rather than disabling the compiler.
  • Lint: Oxlint native React Compiler rules (react/set-state-in-effect, react/immutability, …). Align with [Anti-Patterns](references/anti-patterns.md).

Legitimate effects: useEffectEvent

When setup must stay subscribed (connection, interval, listener) but part of the callback should read latest props/state without re-running setup, extract non-reactive logic with useEffectEvent:

  • Name like user-visible events: onConnected, onTick — not onMount / onUpdate.
  • Call only from Effects (or other Effect Events in the same component); never during render, in event handlers, or as props to children.
  • Omit from the Effect dependency array (enforced by lint).

Do not use useEffectEvent to hide dependencies that should re-trigger the Effect.

Example: [Alternatives §9](references/use-effect-alternatives.md#9-useeffectevent-for-non-reactive-effect-logic). Docs: Separating Events from Effects · useEffectEvent.

When you DON'T need Effects

  1. Transforming data for rendering — compute during render
  2. User events — event handlers
  3. Deriving state — compute it (const x = f(a, b))
  4. Chaining updates — do it in one event handler where possible

Details and fixes: [Anti-Patterns](references/anti-patterns.md). Alternatives: [use-effect-alternatives.md](references/use-effect-alternatives.md).

Decision tree

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? useMemo only if needed (Compiler often makes this unnecessary)
└── Need to reset state when prop changes?
    └── Use KEY PROP on component

Generic components

type Column<T> = {
  key: keyof T;
  header: string;
  render?: (value: T[keyof T], item: T) => React.ReactNode;
};

function Table<T>({ data, columns, keyExtractor }: {
  data: T[];
  columns: Column<T>[];
  keyExtractor: (item: T) => string | number;
}) {
  /* ... */
}

function List<T extends { id: string | number }>({ items }: { items: T[] }) {
  return <ul>{items.map((item) => <li key={item.id}>…</li>)}</ul>;
}

Examples: [generic-components.md](examples/generic-components.md)

React 19 APIs (pointers)

API Use Docs
use() Unwrap promise/context (can suspend) use
useActionState Form action state (RSC/Next-style apps) useActionState
useOptimistic Optimistic UI useOptimistic
useTransition Non-urgent updates useTransition
useEffectEvent Stable callback inside effects useEffectEvent

Short TS notes: [react-19-patterns.md](references/react-19-patterns.md). TanStack Start server mutations → tanstack-start-conventions → [server-functions.md](../tanstack-start-conventions/references/server-functions.md).

Routing (TypeScript only)

Route behavior (validateSearch, loaders, Query, pretty search URLs) → tanstack-router-conventions. Start layout / SSR / server functionstanstack-start-conventions.

Typed route hooks — pass from for inference:

const { userId } = Route.useParams() // in createFileRoute component
const { tab } = Route.useSearch()

validateSearch with Zod is defined on the route file, not in this skill. TS quirks: [tanstack-router.md](references/tanstack-router.md) (canonical copy: tanstack-router-conventionsrouter-typescript.md)

Rules

Always

  • ComponentPropsWithoutRef for native element extension
  • Prefer semantic HTML over generic div/span when the meaning is clear — unslop-code → [semantic-html.md](../unslop-code/references/semantic-html.md)
  • Specific React.*Event<HTMLElement> types
  • Explicit useState when inference fails (null, [], unions)
  • Discriminated unions for variant props
  • ref as prop in React 19
  • React Compiler on; oxlint native react/* compiler rules

Never

  • any on events; JSX.Element for children
  • New forwardRef / useFormState
  • Default useMemo / useCallback / memo without cause
  • useEffect for app data fetching (use loaders/Query)
  • Await a promise you pass to use() for streaming handoff

References

  • [hooks.md](references/hooks.md) — imperative handle, external store typing
  • [event-handlers.md](references/event-handlers.md) — extended event type table
  • [react-19-patterns.md](references/react-19-patterns.md) — ref-as-prop, use() typing notes
  • [anti-patterns.md](references/anti-patterns.md) — derived state, fetch races, effect chains, parent sync
  • [use-effect-alternatives.md](references/use-effect-alternatives.md) — useMemo, key, useSyncExternalStore, useEffectEvent, fetch patterns
  • [generic-components.md](examples/generic-components.md) — Table, Select patterns
  • [tanstack-router.md](references/tanstack-router.md) — Router TS inference (canonical: tanstack-router-conventionsrouter-typescript.md)
  • React — You Might Not Need an Effect · React Compiler
  • Neciu Dan — Start naming your useEffect functions