web-react-dev · diff
git:20260830.050daf6 to git:20260831.1dd02ac
1 added, 0 removed. Audit A to A.
---
name: web-react-dev
description: Use when designing, implementing, reviewing, debugging, testing, or shipping React web client features, including component structure, routing, state ownership, API/data fetching, forms, browser behavior, accessibility, performance, build/deploy, and rendered browser verification. Product-agnostic; use miniapp-product-dev for WeChat/Alipay/Douyin/Baidu mini-programs, app-cross-platform-dev for Flutter/React Native/Android/iOS apps, product-ui-ux-design for UI/UX rules, backend skills for services, and testing-strategy for test-layer planning. Triggers also include "用 React 实现这个前端", "React 组件怎么写", "React 写一个", "Tailwind 怎么写", "Next.js / Vite 项目配置", "重构这个 React 组件/页面(局部)", "refactor a React component/file".
---
# Web React Dev
Use this skill for React web client engineering. It covers browser-rendered React applications, React components, routing, data fetching, forms, frontend API integration, accessibility, performance, build, and deploy checks. It does not own mini-program host behavior, Flutter, native mobile, backend service design, or visual design system rules.
## Routing
- Use `product-rd-workflow` first when the work spans product, design, architecture, implementation, testing, review, and release.
- Use `product-ui-ux-design` before or alongside coding for interaction model, layout, visual hierarchy, density, states, and UI acceptance.
- Use `miniapp-product-dev` for WeChat/Alipay/Douyin/Baidu mini-program pages, host-platform APIs, developer tools, review submission, and release. For React/H5 embedded inside a mini-program webview, this skill owns the React page while `miniapp-product-dev` owns the mini-program shell, bridge, host capabilities, and review/release evidence.
- For Taro projects (React syntax compiled to mini-program runtime): this skill owns the React layer (component decomposition, hooks, state ownership, effect discipline, accessibility primitives) and the **pure** shared layer in the repo's established shared module: DTOs, types, validators, pure mapping functions.
- `miniapp-product-dev` owns Taro lifecycle hooks (`useReady`/`useLoad`/`useDidShow`/`useDidHide`), `Taro.*` runtime APIs, platform branching (`process.env.TARO_ENV`, conditional compilation, platform-specific files), subpackage configuration, host capability adapters, multi-target build invocation, host review/release, and rendered mini-program evidence.
- Shared **runtime adapters** that mini-program targets consume are co-owned with a named final-decision owner per adapter, recorded in the repo. The adapter list and the miniapp acceptance-gate enumeration are canonical in `miniapp-product-dev` (the `Shared runtime adapters consumed by mini-program targets` row under `## Sibling Boundary With web-react-dev`); that gate is blocking and its miniapp contract tests must pass before mini-program targets import the adapter. Web sets browser semantics and cannot merge an adapter change that is browser-safe but mini-program-unsafe. Do not re-add a fixed kill-switch dimension list here: the owner's safety contract names the property (`fail-closed flag evaluation`) and its release contract makes each host platform's gray-release mechanism its own contract, so the dimensions a given adapter needs come from that platform's contract, not from a list on this side. Before merging an adapter change, the merge record must carry the canonical row's gate token and a passing miniapp-contract run recorded on the change under merge (rule canonical in that row); a merge record without the token, or asserting mini-program-safety without the contract run, is a violation.
- When shared code must run in both web and mini-program targets, keep `react-dom`, DOM mutation, browser observers (`IntersectionObserver`/`ResizeObserver`/`MutationObserver`), RAF/layout APIs, and other browser globals out of the shared layer; use Taro cross-platform equivalents at the consumer side.
- Use `app-cross-platform-dev` for Flutter, React Native, native Android, native iOS, app store release, and device-native capability work.
- Use Go or Python backend skills for API/service ownership, persistence, auth services, queues, and server contracts.
- For backend HTTP integrations, preserve current client wire behavior unless an explicit consumer-migration decision exists. Classify JSON vs protobuf-backed HTTP using `../platform-service-connectivity/references/protobuf-http-contract-signals.md`.
- First decide whether the client diff touches the HTTP contract or wire behavior. Wire-unchanged UI/component/state work does not need a backend owner round-trip and must not claim backend contract conformance.
- For unrelated client work, classify the diff with the canonical gate. If the surface is out of scope, client work may continue without claiming backend contract conformance.
- If the canonical gate classifies the diff as in scope, confirm the backend's recorded wire format or route back to the backend contract owner.
- Routine JSON/OpenAPI changes use the existing API contract record and do not require backend wire-format confirmation when the canonical reference classifies the surface as out of the protobuf wire-format gate.
- Client API wrappers must consume the backend contract's recorded response envelope per `../platform-service-connectivity/references/http-response-envelope-contract.md`: for surfaces on the canonical `code`/`message`/`data` envelope, components and domain state read typed business data from `data`; other shipped or non-JSON envelopes are consumed per their recorded contract. Read only fields present in the recorded contract — do not infer business fields from unrecorded top-level or fallback shapes — and scatter no duplicate envelope parsing across the client.
- If backend wire-format evidence is unreachable for an in-scope surface, stop at `pending-contract-owner`, name the backend owner or owning repo, record the attempted lookup, and set the next escalation path. An assumed-wire-format note never unblocks merge. The blocker clears only when a checkable owner record, quoted prior backend record, or explicit migration decision is available; if no owner responds within the team's review SLA, keep the client change blocked or downscope the touched wire-format surface and record the dropped surface as an open owner-routed gap. Do not claim backend contract conformance or completion for the removed slice.
- Do not fork IDL or hand-maintain duplicated DTOs in the web repo.
- Use `testing-strategy` to choose unit/component/API/E2E layers; return here for React-specific implementation.
- Use `test-artifact-management` when the ask is about generating structured test cases from a Feishu requirements doc or codebase and tracking them in Feishu Bitable before implementation begins.
- Use `defect-diagnosis` first for failed tests, browser bugs, hydration/rendering issues, flaky UI, API integration symptoms, or production regressions.
- For money, quota, permission, tenant/user data, high-impact AI, repeated submit, async finality, or support-traceable incidents, apply `product-rd-workflow` high-risk resilience gates before treating the UI as complete.
## Core Workflow
Before editing components, routes, state, API clients, styles, configs, or tests, complete enough analysis and planning for the change to be reviewable. Scale the plan to risk: a simple low-risk single-component change can use a short inline plan; multi-file, API-visible, accessibility-sensitive, release, bug-fix, branch/MR, unclear-risk, or high-risk work needs explicit task split, acceptance checks, verification commands, rollback or stop conditions, and named handoffs to testing, miniapp/app, backend, or diagnosis skills before edits. Runtime-visible work additionally consumes the canonical UI/UX delivery contract's Design brief and Test selection Phase 0 before the first implementation edit.
Repo-local agent contracts (`AGENTS.md` at the repo root and in source directories) are part of the delivery contract: when a change moves a stable boundary, generated surface, workflow, or directory-local rule, update the nearest contract in the same MR and keep coverage in sync per `product-rd-workflow`'s spec / repo-contract sync gate.
When checking a React project against team standards, split findings into deterministic checks and agent review checks. Deterministic checks cover package scripts, typecheck/lint/test/E2E commands, generated API client usage, environment configuration, CI gates, bundle/performance budgets, and request/trace identifier propagation in central clients. Agent review checks cover component ownership, state placement, API contract alignment, finite-value mapping, accessibility/design quality, and whether tests assert behavior instead of only rendering. For the concrete deterministic executor list (ecosystem linter/analyzer rules — `eslint-plugin-react-hooks`, `@typescript-eslint` typed rules, `dependency-cruiser`, tsconfig `strict`/`noUncheckedIndexedAccess`) and the shipped client language-basics conformance checkers, see `testing-strategy/references/fitness-functions.md` §4.1.3 (client language-basics; spec 006). Prefer enabling ecosystem rules over hand-rolling checks.
1. Define the web surface.
- Route/page, component boundary, URL params/query state, auth/permission state, responsive breakpoints, and browser support.
- User-visible states: loading, skeleton, empty, partial, success, error, retry, disabled, permission denied, stale/offline, and optimistic update.
- Data boundary: API client, request cancellation, cache/revalidation, mutation invalidation, pagination, streaming/websocket if used, and typed error mapping.
- API observability: central clients should attach or preserve request/trace/operation identifiers, measure duration, distinguish cancel from failure, classify upload or long-running requests, and map backend envelopes into typed user-facing errors.
- Finite-value boundary: generated API enums, backend string codes, URL query values, route params, filters, analytics dimensions, and display labels should flow through one typed client/domain mapping module. Components should use the mapped symbols and label tables instead of scattering raw values such as `"US"`, `"CN"`, `"active"`, or `"default"` in render, tests, routing, or tracking code. If shared client-domain ownership is unclear, keep a local mapper for the slice, mark temporary duplicate/raw uses with `finite-value-debt: <task-ref> <owner> <deadline> <reason>`, and record the consolidation owner. Architecture owns the cross-stack semantic decision when the same value must align across web, app, mini-program, backend, storage, and analytics.
2. Analyze the existing web surface.
- Locate the owning route/page, component tree, state owner, API client, data-fetching layer, styling system, tests, and build scripts before editing.
- Identify whether state belongs in URL/query params, cache/server state, form state, local component state, browser storage, or global app state.
- Read repo wrappers first: package manager, dev/build scripts, lint/typecheck/test runners, browser/E2E tools, environment variables, and generated clients.
+ - Before generating component-library code, take the project's ground truth from the library's own introspection surface — its config file (e.g. `components.json`), official info/inspect CLI or MCP when the library ships one, otherwise the installed package's exports/types — for framework, aliases, installed components, and the exact installed version; write APIs against that version, never from memory of "current" APIs (prop names and defaults shift across majors). After editing, close with the library's own linter/codemod check on the changed files when one exists (deprecated-usage and a11y rules the generic lint config does not know); for a library major-version migration, follow the official migration checklist + changelog for the exact from→to pair, apply, then re-run the library lint to prove no deprecated usage remains.
- If a design exists, map visible states and interactions to component ownership before implementing.
- For every visible UI change, load `../product-ui-ux-design/references/delivery-contract.md` and consume either its full Design brief + Phase 0 or its valid low-risk copy-only record + lightweight Phase 0 before coding. The lightweight path checks semantics, accessible name, localization, rendered extent, and target render without inventing unrelated matrices; risk-bearing copy uses the full path. For full slices, map structure, state/adaptation matrices, behavior and criteria to React ownership; record route/server, component/state owners, viewports/themes/input modes, and preserved behavior. When React is embedded in a native WebView, mini-program `web-view`, or Electron shell, this skill owns the content-layer member; the native/mini/desktop host owner must add its separate entry, binding and runtime record, even when host code is unchanged.
- Before the first implementation edit, add the canonical `client_entry` defined there: local rule identifier or short quote and implementation decision, target surface/runtime, planned run/capture command, and behavior that must remain unchanged.
3. Structure React code by ownership.
- Decompose UI by responsibility, not by arbitrary visual fragments.
- Put state at the lowest owner that needs to read/write it; lift only when siblings need shared state.
- Keep derived data derived during render or memoized only when measured or clearly necessary.
- Avoid Effects for pure derived state, event handling, or data transformations that can happen during render.
- Isolate side effects: network, subscriptions, timers, storage, analytics, and imperative browser APIs.
- Keep route loaders/actions, client caches, or data-fetching libraries aligned with the repo pattern.
4. Implement browser behavior deliberately.
- Forms need validation, submit pending state, disabled/retry behavior, server error mapping, and keyboard behavior.
- Navigation needs route guards, deep links, back/forward behavior, scroll/focus restoration, and not-found/permission states.
- Tables/lists need stable keys, empty/error rows, pagination or virtualization when needed, persisted filters where useful, selected-count state, bulk operation feedback, clear reload/reset behavior after actions, and non-janky loading.
- Workbench pages need explicit route/layout ownership, context strips, active job/task entries, permission-gated actions, and drawer/detail inspection that preserves parent context.
- Workbench layout needs code-level geometry: bounded shell/header/control/work regions, sticky or preserved context, named collapse rules, stable empty/loading/error geometry, and secondary panels that collapse before primary content becomes unreadable.
- Complex workbench variants are reference-level material, not entrypoint material. If the surface is a dense review, report, assignment, resource, assistant, media/capture, or app-hosted workspace, load `references/complex-workspace-patterns.md` and apply only the relevant pattern family.
- In complex workspaces, declare state owners for route/context, selection, filters, permissions, async jobs, restored preferences, media readiness, submit/finality, and child drawers/panels before coding. Validate restored state against the current route, identity, permission, task type, and available item count.
- Mature workspace shells should implement code-level contracts, not only CSS: token-to-theme binding, startup context, route/permission-derived navigation, durable jobs, measured overflow, secondary-panel collapse, upload/parse state machines, and browser screenshot acceptance at declared stress widths.
- Token provenance must be visible in code: map design tokens into the component-library theme first, then local CSS should reference theme variables or documented semantic values.
- Workbench shell responsiveness needs explicit code thresholds: minimum widths, fallback layout, scroll owner, sticky enablement, and collapse order.
- Embedded, hosted, or app-container web shells need code-level ownership for entry paths, host/source detection, allowlisted origins, defensive message parsing, layout switching, persisted host flags, normal-browser fallback, lifecycle restore, and storage failure recovery.
- Auth, account, assistant, report, assignment, resource, media/capture, and AI-recognition variants are detailed in `references/complex-workspace-patterns.md`; do not keep their source-specific state catalogs in this entrypoint.
- Long work, high-risk submits, destructive actions, and AI/data operations need pending/final state, duplicate-submit protection, timeout/failure UI, retry/recovery, and a stable visible identifier when support or reconciliation may be needed.
- Configurable shortcuts or command palettes need a parsed and normalized registry, platform-aware display labels, reserved/non-rebindable shortcut checks, duplicate and conflict warnings before lossy config parsing, explicit scope/context priority, user override plus explicit unbind semantics, invalid-config fallback to defaults, reload/delete cleanup, command action allowlists, and collision-safe discovery UI. Dispatch must isolate shortcuts from text inputs, editable fields, composition/IME, modal focus traps, and command palette focus; chords or multi-step sequences need timeout/cancel handling, propagation rules, and cleanup on unmount.
- Chart, canvas, image, PDF, annotation, dense table, card, menu, browser storage, and cross-tab behavior need lifecycle cleanup, measured overflow, accessibility, and browser evidence at realistic container widths.
5. Debug systematically when behavior is wrong.
- Reproduce with the smallest page, route, component test, browser trace, or network fixture that shows the failure.
- Classify the failure by layer: route, render/hydration, component state, effect/subscription, API contract, cache/revalidation, browser storage, permission/auth, build/env, or deployment/cache.
- Inspect console errors, failed network requests, request/response payloads, React warnings, route params, cache state, feature flags, and environment variables before changing code.
- Prove whether the issue is browser-only, data-contract, state ownership, styling/layout, or backend behavior; route backend fixes to backend skills.
- Add regression evidence at the lowest sufficient layer, then run browser smoke for visible flows.
6. Verify in a real browser.
- Run the repo's formatter, typecheck, lint, unit/component tests, and build or affected checks.
- When writing the test code itself (structure, naming, smells, fixtures, behavior-vs-state, coverage, isolation, parameterization), pick the matching § from the decision table in `testing-strategy/references/test-code-authoring-patterns.md`; enable the per-stack lint executors for its machine-decidable smells (conditional logic / sleep / assertion-free tests) per `testing-strategy/references/fitness-functions.md` §4.1.4 (Jest/Vitest/Playwright ESLint rules).
- **TC traceability**: link tests via the `createTcSuite(test, describe)` factory wrapper. Registers at collection time so `.skip` / `.skipIf` / `.todo` still map to Bitable status. Full overloads supported: `.concurrent` / `.each` / `(name, options, fn)` / `(name, fn, timeout)`. Helper from `test-artifact-management/references/tc_helpers/tc.ts`, installed under `test/tc.ts`. See `test-artifact-management/references/tc-marker-conventions.md`. Before adding tests, `grep -rn 'tcTest\|tcDescribe' src/ __tests__/` plus the sidecar `test/results/tc-map.jsonl` to check for existing coverage — extend rather than duplicate. When a TC is marked 废弃, grep both source and sidecar; follow deprecation cascade in `testing-strategy`. Tests without any TC link: prompt user only when the underlying code is also removed.
- **废弃级联:业务代码是否仍在用** — TS/JS 用 `madge` 拿依赖图最准,没安装则 grep 兜底:
1. `npx madge --dependents src/path/to/Module.tsx`(列出谁 import 了它);或 `grep -rEn "from ['\"][./]*<path>" src/`
2. 排除测试文件后还有 import → 产品代码在用,不删;只剩这个测试 → 同 commit 删模块 + 测试
3. 路由级别另查:`grep -rn "<RouteComponent>" src/router src/routes`;运行时 lazy import (`React.lazy(() => import('...'))`) madge 能抓但要 `--include-npm` 等参数核对
4. 边界:路径别名(`@/foo`)需 madge 的 `tsconfig` 配;动态 `import(name)` 字面值为变量时 grep 抓不到;CSS / 静态资源 import 的 dead-asset 由 build 报告
- For API-backed UI, test component states, API client parsing/error translation, and at least one browser/E2E smoke path when feasible.
- Inspect the rendered page in a browser for any visible UI change, responsive behavior, empty/error states, and console/network errors.
- For UI/UX redesign evidence, include the declared stress viewport, or when none exists use the minimum supported width plus one narrow stress width such as 320px; text wrapping/overflow; loading/empty/error/final states; keyboard/focus path; and a browser screenshot or equivalent visual artifact. Mark each dimension covered or `N/A` with a one-line reason; `N/A` is valid only when the reason names a verifiable structural fact, explains why that fact makes the dimension unreachable or unchanged for this slice, and includes a checkable pointer such as a file path, config key, or commit that resolves at review time. Persist evidence artifacts where reviewers can access them using sanitized/test accounts and redacting tokens, PII, credentials, private paths, and raw personal data; delete temporary smoke pages or helper scripts before commit unless the repo intentionally owns them.
- Return the complete canonical client-record member defined in `../product-ui-ux-design/references/delivery-contract.md` for testing Phase 1 and the design verdict. The member includes its applied rule/decision, affected files/components, preserved behavior, exact command, immutable candidate binding, producer member/version actually exercised, artifacts, tested route/server, viewport/container sizes, themes/input modes/states, criterion-mapped observations, console/network checks, coverage boundary, and gaps. The browser render proves only the captured content layer; it cannot close an embedded host or unbound producer member. `testing-strategy` records aggregate sufficiency before the design owner records the candidate-bound verdict.
- For browser-runtime changes, browser smoke is a completion gate when lower layers cannot prove the behavior. This includes changes to routing, browser storage/session restore, streaming/fetch finality, visibility or foreground/background behavior, permission/capability prompts, WebView bridge callbacks, upload/media flows, and rendered loading/error/final states. If the browser or app server is missing, first attempt normal setup; if still unavailable, stop at `pre-runtime-test-ready` or `blocked` and name the owner, attempted commands, residual risk, and next unblock action. `pre-runtime-test-ready` is handoff-only, not merge-ready, release-ready, or complete.
- Check accessibility names, labels, focus order, keyboard navigation, aria only when semantic HTML is insufficient, contrast, and text wrapping.
- Check performance when relevant: bundle impact, unnecessary renders, long lists, image loading, code splitting, hydration/runtime errors, and Core Web Vitals risk.
## Non-Negotiable Rules
- Do not use mocked happy-path component tests as proof that API integration works.
- Do not add Effects for state that can be derived from props/state during render.
- Do not ship user-visible UI without inspecting the rendered browser surface when layout or interaction changed.
- Do not add hidden keyboard traps, icon-only controls without accessible names, or mouse-only critical actions.
- Do not ship configurable shortcuts as scattered `keydown` handlers; centralize parsing, normalization, scope resolution, reserved-key enforcement, unbind/override behavior, and text-input or modal isolation.
- Do not let server transport errors leak directly into user copy; map them to useful UI states.
- Do not ship high-risk actions with only optimistic UI or generic success/error toasts; users must be able to tell whether the operation is pending, succeeded, failed, retryable, blocked, or needs support.
- Do not treat a frontend API client as done until empty response, invalid JSON, non-2xx envelope, auth expiry, network failure, cancellation, and backend error message extraction are covered at the client or component boundary when relevant.
- Do not scatter backend enum/string literals through React components, URL/query handling, analytics, or tests. Centralize finite-value parsing, display labels, defaults, and unknown-value behavior at the API/client-domain boundary, and keep raw literals only in clearly named boundary conversion tests that cover every known external value plus unknown/default behavior. Migrate existing non-boundary test raw literals for that value in the same pull request or mark each remaining use with `finite-value-debt: <task-ref> <owner> <deadline> <reason>`, even when the current slice does not introduce a new mapper.
- Do not debug React/browser failures from code inspection alone when a browser reproduction, console output, network trace, screenshot, or focused test can be collected.
- Do not claim a web client fix is complete without naming the browser/rendered verification that was run. If required browser/runtime verification is unavailable after remediation, the status is `pre-runtime-test-ready` or `blocked`, not complete.
## Reference Loading
- For source provenance, current extraction boundary, and keep/merge/discard decisions, read `references/source-evidence-map.md` when auditing or re-extracting this skill.
- For embedded H5 inside a host (mini-program `web-view` / native WebView / payment / vendor app WebView) — H5-author POV: env detection, bridge abstraction, auth-from-host (cookieless), hardware-back integration, safe-area + viewport-fit, host capability degradation, WeChat JSSDK specifics, offline / lifecycle, cross-app navigation, anti-patterns, multi-host smoke matrix — read `references/embedded-h5-in-host.md`. The host-side contract (web-view component / WebView shell config / native bridge setup) is owned by `miniapp-product-dev` (mini-program host) and `app-cross-platform-dev` (native WebView shell).
- For joint extraction from Figma design source AND a React/web monorepo (with package class mapping, design-token cross-validation, deprecation-marker detection), read `../skill-extraction-workflow/references/two-source-extraction-pattern.md`. Use when both sources are available; produces aligned design + implementation rules with cross-source token validation.
- For component decomposition, state ownership, effects, routing, forms, and data fetching, read `references/react-architecture.md`.
- For dense review, report, assignment, resource, assistant, media/capture, or app-hosted workspace state-machine patterns, read `references/complex-workspace-patterns.md`.
- For browser accessibility, keyboard/focus, responsive behavior, and visual verification, read `references/web-ui-quality.md`.
- For API integration, caching, error handling, testing, performance, build, and deployment readiness, read `references/web-quality-release.md`.