mcpField
R
react-dev

react-dev

github.com/fixmyberlinDevelopment065 installsUpdated 3d ago
Repository

About react-dev

A FixMyBerlin/FMC skill for React and TypeScript component conventions, especially typing and disciplined use of `useEffect`. It is intended for developers writing or reviewing React code and points routing and server-side work to related skills.

Key features

  1. 01React 19 component and ref typing
  2. 02Named `useEffect` functions
  3. 03Guidance on when to avoid effects
  4. 04React Compiler and Oxlint conventions
  5. 05React 19 API usage notes

Use cases

  1. 01Typing component props and event handlers
  2. 02Reviewing or writing effect logic
  3. 03Avoiding effects for derived state or fetching
  4. 04Applying React Compiler and lint conventions

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/fixmyberlin/fixmyskills --skill react-dev

After installing, type/react-devin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

examples/
generic-components.md
references/
effects.md
event-handlers.md
react-19-patterns.md
tanstack-router.md

Details

From the project README

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

React + TypeScript (FMC)

FMC conventions for React typing and useEffect discipline (naming, scope, when to skip). Routing and server I/O live in sibling skills (below).

FMC stack (required)

RequirementRule
React 19Target 19.x; no forwardRef / useFormState / useActionState in new code; forms: TanStack Form
React CompilerEnabled in the app build — auto-memoization is the default
LintOxlint react plugin — native Compiler rules on by default, plus 'react/unsupported-syntax': 'error'; no eslint-plugin-react-hooks jsPlugin
MemoizationDo not add useMemo / useCallback / memo by default; add only when profiling or a lint rule requires it
TanStack StartServer I/O and mutations → tanstack-start-conventions (this skill covers component typing only)
Data fetchingRoute loaders + React Query — not useEffect fetch (see tanstack-router-conventions)

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

Related skills

TopicSkill
Routes, loaders, validateSearchtanstack-router-conventions
URL state (prefer router search)tanstack-router-conventions
SSR, server functions, Start layouttanstack-start-conventions
Folder layout, thin routes (Start)skill tanstack-start-conventions → references/app-structure.md
createServerFn, server mutationsskill tanstack-start-conventions → references/server-functions.md
Client stores (not context + reducer)zustand-state-management
Semantic HTML (div/span leftovers)skill unslop-code → references/semantic-html.md

Typing notes

  • Props: extend native elements with React.ComponentPropsWithoutRef<'button'> (ref excluded); children: React.ReactNode, never JSX.Element.
  • Variant props: discriminated unions ({ variant: 'link'; href: string } | { variant: 'button'; onClick: () => void }) and narrow on the discriminant.
  • ref: normal prop in React 19, no new forwardRef → react-19-patterns.md.
  • Events: specific React.*Event<HTMLElement> types so currentTarget is typed; never any → event-handlers.md.
  • Hooks: explicit useState<User | null>(null) for null, [], unions; useRef<HTMLInputElement>(null) + ?. for DOM, useRef(0) for mutable box; discriminated union for useReducer actions; createContext<T | null>(null) + throwing custom hook. External store: useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot).
  • Route hooks: Route.useParams() / Route.useSearch() inside createFileRoute components; validateSearch lives in the route file → tanstack-router.md.

useEffect — naming, scope, and when to skip

Effects are an escape hatch for synchronizing with external systems (non-React widgets, browser APIs, map SDKs, subscriptions, analytics). If no external system is involved, you usually should not use an Effect.

Name every useEffect

Always pass a named function expression to useEffect, not an anonymous arrow. Default style for new and edited code, including effects inside custom hooks. Name non-trivial cleanups too.

useEffect(
  function updateDocumentTitle() {
    document.title = `${count} items`
  },
  [count],
)

useEffect(function pollServerForUpdates() {
  const intervalId = setInterval(/* ... */, 5000);
  return function stopPollingServer() {
    clearInterval(intervalId);
  };
}, [serverId]);
Indicators from naming

Naming is a design review at the keyboard. Details: effects.md.

SignalMeaningFix
Name needs "and" / "also"Unrelated concerns in one effectSplit into separate effects, each with one name
syncDerivedValue, updateStateFromState, setXBasedOnYDerived state or state-to-state syncDerive during render
notifyParentOfChange, reportStateToParentParent updates driven by child stateCall in the event handler, lift data up, or make the component controlled
resetFormOnSubmitFlagUser intent expressed via state hopHandle in the event handler
persistOnClose, syncWhenClosed, saveDraftOnDismissSide effect on dismiss/open UI stateHandler, not Effect on isOpen (effects.md §3)
Clear external verbs: connectTo…, subscribeTo…, initialize…, synchronize… (browser, network, map SDK)Often legitimate Effect territoryStill name them; add cleanup when needed

If the honest name sounds like internal React bookkeeping, the code belongs in render, an event handler, or a different pattern.

Quick reference
SituationDON'TDO
Derived state from props/stateuseState + useEffectCalculate during render (no useMemo by default, Compiler is on)
Reset state on prop changeuseEffect with setStatekey prop
User event responsesuseEffect watching stateEvent handler directly
Persist/sync on dismissuseEffect on isOpenDismiss handler (or onCloseComplete)
Notify parent of changesuseEffect calling onChangeCall in event handler, or controlled component
Data from child to parentEffect calling onFetchedParent fetches, passes down
External storeEffect + useStateuseSyncExternalStore
Fetch datauseEffectRoute loaders + React Query

Strict Mode (dev): effects run setup twice on mount. Add teardown for subscriptions and timers; guard one-time init (module-level didInit guard, see effects.md §6).

Effects and React Compiler / lint
  • 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, …).
useEffectEvent

For effects that must stay subscribed (connection, interval, listener) while part of the callback reads latest props/state. Example: effects.md §7.

  • 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 dependency array (enforced by lint); never use it to hide dependencies that should re-trigger the Effect.

React 19 APIs (pointers)

APIUseDocs
use()Unwrap promise/context (can suspend)use
useOptimisticOptimistic UIuseOptimistic
useTransitionNon-urgent updatesuseTransition
useEffectEventStable callback inside effectsuseEffectEvent

Rules

Always

  • Named useEffect functions; React Compiler on; oxlint native react/* compiler rules
  • Prefer semantic HTML over generic div/span — skill unslop-code → references/semantic-html.md
  • ref as prop in React 19

Never

  • New forwardRef / useFormState / useActionState (forms: TanStack Form)
  • 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

  • effects.md — read when writing or reviewing a useEffect, or an effect name hits the smell table above (reset with key, persist-on-gesture, parent data flow, init guard, useEffectEvent example)
  • event-handlers.md — read when typing event handlers beyond click/submit/change, or forwarding events via props
  • react-19-patterns.md — read when typing ref as prop, use(), or migrating a legacy codebase to React 19
  • generic-components.md — read when writing generic components (constrained T extends HasId, Select<T> with accessors)
  • tanstack-router.md — read when typing route hooks (canonical: tanstack-router-conventions → router-typescript.md)
  • Neciu Dan — Start naming your useEffect functions

Comments

Markdown supported