Default to function components + Hooks. Routing, data fetching, CSS, state libraries, and build tools follow the project; do not specify Next / Remix / Vite in this skill.
Do not write APIs from training data. First determine the minor, then read the corresponding reference.
Determine the version
- Read the installed
reactversion (node_modules/react/package.json'sversion, or the lockfile). Do not only look atpackage.json's^range.reactandreact-dommust be the same minor. - Take minor(
19.2.8→19.2), open the file in the table below, and write code according to that file.
| minor | File |
|---|---|
| 19.0 | references/19.0.md |
| 19.1 | references/19.1.md |
| 19.2 | references/19.2.md |
For newer minors not listed: use the highest covered minor as the base, then check the official blog / changelog for that minor. For older ones: do not use the new APIs in this skill. React 18 should not apply this skill's 19 APIs.
Do not use Effects to synchronize React internal state
Effects are only for synchronizing withexternal systems(DOM plugins, WebSocket, non-React widgets). If it can be computed during render, do not put it into useEffect + setState。
| What you want to do | How to write it |
|---|---|
| Derive from props/state | Compute directly during render. Use useMemoif expensive (not needed if the project has React Compiler enabled) |
| The user clicked a button / submitted a form | Event handler or Action, not an Effect |
| Reset the state of an entire subtree | Give the component a stable business key, not useEffect(() => setX(init), [id]) |
| List selected item | Store selectedId, during render items.find; do not store another copy of the object and align it with an Effect |
| Notify the parent component | Call the callback in the event, not in an Effect after render onChange(value) |
| Fetch data | Follow the project's existing framework / library; only consider an Effect if there is none. Do not hand-roll a fetch+loading setup in every component |
Do not disable lint just to "write fewer dependencies". What should go in the dependencies should go in; 19.2's useEffectEvent is only for "events triggered inside an Effect", see the 19.2 section.
State and data flow
- If it can be computed, do not store it.
fullName = first + ' ' + last, do not keep another copy in state. - Forms: prefer uncontrolled +
<form action={...}>. Use controlled only when per-keystroke response is required. - Use Action(
startTransitionto mutate server data, wrapping async, oruseActionState/ formaction), do not hand-writeisPending+try/finallyboilerplate. use()to read a Promise or Context. The Promise must come from the framework /cache/ a resource already cached by the parent component,forbiddenin a Client component's renderuse(fetch(...))。- Function component
refaccept it as a normal prop. Do not wrap it again inforwardRef。 - Context directly as a provider:
<ThemeContext value={v}>, not<ThemeContext.Provider>。 - Cross-layer state: Context or the project's existing store. Do not create another layer just for prop drilling.
Components
- Do not let a single file grow into a giant one (about 500 lines); the page orchestrates routing/entry, split out UI blocks and
useXxx. - List
keyUse stable ids, not indexes (unless static and never reordered). - Keep props passed to list items as stable as possible: compute
activebefore passing it in; don't have every item receive aactiveId。 - Document metadata: write it directly in the component with
<title>/<meta>/<link>, and React will hoist it tohead. If the project already has a metadata library, follow the library. "use server"only marks Server Action, not a Server Component. If there is no framework RSC support, don't write it.