Token导航 LogoToken导航TokenDH.com
研究检索需要联网github未标认证来源可访问clear审计未展示

react-19React 19 文档

Agent Skill

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。它适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码,整理组件结构,或定位布局和性能问题。使用时需要结合项目现有设计系统、路由和构建方式,避免只生成孤立片段;涉及页面改动时,应配合本地预览和构建检查确认视觉效果。

总安装

1,706

周安装

69

GitHub Stars

公开资料未说明

下载量

535
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:react-19(React 19 文档)
来源仓库:https://github.com/noklip-io/agent-skills
仓库路径:skills/react-19
安装命令:
npx skills add noklip-io/agent-skills --skill "react-19"
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

AgentSkills.tonpx skills
npx skills add noklip-io/agent-skills --skill "react-19"

简介

提供 React 19 版本的官方文档和技术参考资料。

  • 包含新特性说明、API 变更和使用示例。适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。
  • 帮助开发者快速掌握 React 19 的更新内容和迁移要点。
  • 建议配合实际项目代码验证文档内容的适用性。
  • react-19 属于研究检索类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

name
react-19
description
>
Trigger
When writing React 19 components/hooks in .tsx (ref as prop, new hooks, Actions, deprecations).
license
MIT
metadata
author
noklip-io
version
1.0
scope
[root, ui]
auto_invoke
Writing React 19 components
allowed-tools
Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task

React 19 - Key Changes

This skill focuses on what changed in React 19. Not a complete React reference.

Coming from React 16/17?

If upgrading from pre-18 versions, these changes accumulated and are now mandatory:

ChangeIntroducedReact 19 Status
createRoot / hydrateRootReact 18Required (ReactDOM.render removed)
Concurrent renderingReact 18Foundation for all R19 features
Automatic batchingReact 18Default behavior
useId, useSyncExternalStoreReact 18Stable, commonly used
Hooks (no classes for new code)React 16.8Only path for new features
createContext (not legacy)React 16.3Required (legacy Context removed)
Error BoundariesReact 16Now with better error callbacks

Migration path: Upgrade to React 18.3 first (shows deprecation warnings), then to 19.

The React 19 Mindset

React 19 represents fundamental shifts in how to think about React:

Old ThinkingNew Thinking
Client-side by defaultServer-first (RSC default)
Manual memoizationCompiler handles it
useEffect for dataasync Server Components
useState for formsForm Actions
Loading state booleansSuspense boundaries
Optimize everythingWrite correct code, compiler optimizes

See references/paradigm-shifts.md for the mental model changes.

See references/anti-patterns.md for what to stop doing.

Quick Reference: What's New

FeatureReact 18React 19+
MemoizationManual (useMemo, useCallback, memo)React Compiler (automatic) or manual
Forward refsforwardRef() wrapperref as regular prop
Context provider<Context.Provider value={}><Context value={}>
Form stateCustom with useStateuseActionState hook
Optimistic updatesManual state managementuseOptimistic hook
Read promisesNot possible in renderuse() hook
Conditional contextNot possibleuse(Context) after conditionals
Form pending stateManual trackinguseFormStatus hook
Ref cleanupPass null on unmountReturn cleanup function
Document metadatareact-helmet or manualNative <title>, <meta>, <link>
Hide/show UI with stateUnmount/remount (state lost)<Activity> component (19.2+)
Non-reactive Effect logicAdd to deps or suppress lintuseEffectEvent hook (19.2+)
Custom ElementsPartial supportFull support (props as properties)
Hydration errorsMultiple vague errorsSingle error with diff

React Compiler & Memoization

With React Compiler enabled, manual memoization is optional, not forbidden:

// React Compiler handles this automatically
function Component({ items }) {
  const filtered = items.filter(x => x.active);
  const sorted = filtered.sort((a, b) => a.name.localeCompare(b.name));
  const handleClick = (id) => console.log(id);
  return <List items={sorted} onClick={handleClick} />;
}

// Manual memoization still works as escape hatch for fine-grained control
const filtered = useMemo(() => expensiveOperation(items), [items]);
const handleClick = useCallback((id) => onClick(id), [onClick]);

When to use manual memoization with React Compiler:

  • Effect dependencies that need stable references
  • Sharing expensive calculations across components (compiler doesn't share)
  • Explicit control over when re-computation happens

See references/react-compiler.md for details.

ref as Prop (forwardRef Deprecated)

// React 19: ref is just a prop
function Input({ placeholder, ref }) {
  return <input placeholder={placeholder} ref={ref} />;
}

// Usage - no change
const inputRef = useRef(null);
<Input ref={inputRef} placeholder="Enter text" />

// forwardRef still works but will be deprecated
// Codemod: npx codemod@latest react/19/replace-forward-ref

Ref Cleanup Functions

// React 19: Return cleanup function from ref callback
<input
  ref={(node) => {
    // Setup
    node?.focus();
    // Return cleanup (called on unmount or ref change)
    return () => {
      console.log('Cleanup');
    };
  }}
/>

// React 18: Received null on unmount (still works, but cleanup preferred)
<input ref={(node) => {
  if (node) { /* setup */ }
  else { /* cleanup */ }
}} />

Context as Provider

const ThemeContext = createContext('light');

// React 19: Use Context directly
function App({ children }) {
  return (
    <ThemeContext value="dark">
      {children}
    </ThemeContext>
  );
}

// React 18: Required .Provider (still works, will be deprecated)
<ThemeContext.Provider value="dark">
  {children}
</ThemeContext.Provider>

New Hooks

useActionState

import { useActionState } from 'react';

function Form() {
  const [error, submitAction, isPending] = useActionState(
    async (prevState, formData) => {
      const result = await saveData(formData.get('name'));
      if (result.error) return result.error;
      redirect('/success');
      return null;
    },
    null // initial state
  );

  return (
    <form action={submitAction}>
      <input name="name" disabled={isPending} />
      <button disabled={isPending}>
        {isPending ? 'Saving...' : 'Save'}
      </button>
      {error && <p className="error">{error}</p>}
    </form>
  );
}

useOptimistic

import { useOptimistic } from 'react';

function Messages({ messages, sendMessage }) {
  const [optimisticMessages, addOptimistic] = useOptimistic(
    messages,
    (state, newMessage) => [...state, { ...newMessage, sending: true }]
  );

  async function handleSubmit(formData) {
    const message = { text: formData.get('text'), id: Date.now() };
    addOptimistic(message); // Show immediately
    await sendMessage(message); // Reverts on error
  }

  return (
    <form action={handleSubmit}>
      {optimisticMessages.map(m => (
        <div key={m.id} style={{ opacity: m.sending ? 0.5 : 1 }}>
          {m.text}
        </div>
      ))}
      <input name="text" />
    </form>
  );
}

use() Hook

import { use, Suspense } from 'react';

// Read promises (suspends until resolved)
function Comments({ commentsPromise }) {
  const comments = use(commentsPromise);
  return comments.map(c => <p key={c.id}>{c.text}</p>);
}

// Usage with Suspense
<Suspense fallback={<Spinner />}>
  <Comments commentsPromise={fetchComments()} />
</Suspense>

// Conditional context reading (not possible with useContext!)
function Theme({ showTheme }) {
  if (!showTheme) return <div>Plain</div>;

  const theme = use(ThemeContext); // Can be called conditionally!
  return <div style={{ color: theme.primary }}>Themed</div>;
}

useFormStatus (react-dom)

import { useFormStatus } from 'react-dom';

// Must be used inside a <form> - reads parent form status
function SubmitButton() {
  const { pending, data, method, action } = useFormStatus();
  return (
    <button disabled={pending}>
      {pending ? 'Submitting...' : 'Submit'}
    </button>
  );
}

function Form() {
  return (
    <form action={serverAction}>
      <input name="email" />
      <SubmitButton /> {/* Reads form status via context */}
    </form>
  );
}

See references/new-hooks.md for complete API details.

Form Actions

// Pass function directly to form action
<form action={async (formData) => {
  'use server';
  await saveToDatabase(formData);
}}>
  <input name="email" type="email" />
  <button type="submit">Subscribe</button>
</form>

// Button-level actions
<form>
  <button formAction={saveAction}>Save</button>
  <button formAction={deleteAction}>Delete</button>
</form>

// Manual form reset
import { requestFormReset } from 'react-dom';
requestFormReset(formElement);

Document Metadata

// Automatically hoisted to <head> - works in any component
function BlogPost({ post }) {
  return (
    <article>
      <title>{post.title}</title>
      <meta name="description" content={post.excerpt} />
      <meta name="author" content={post.author} />
      <link rel="canonical" href={post.url} />
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </article>
  );
}

Resource Preloading

import { prefetchDNS, preconnect, preload, preinit } from 'react-dom';

function App() {
  // DNS prefetch
  prefetchDNS('https://api.example.com');

  // Establish connection early
  preconnect('https://fonts.googleapis.com');

  // Preload resources
  preload('https://example.com/font.woff2', { as: 'font' });
  preload('/hero.jpg', { as: 'image' });

  // Load and execute script eagerly
  preinit('https://example.com/analytics.js', { as: 'script' });

  return <main>...</main>;
}

Stylesheet Support

// precedence controls insertion order and deduplication
function Component() {
  return (
    <>
      <link rel="stylesheet" href="/base.css" precedence="default" />
      <link rel="stylesheet" href="/theme.css" precedence="high" />
      <div className="styled">Content</div>
    </>
  );
}

// React ensures stylesheets load before Suspense boundary reveals
<Suspense fallback={<Skeleton />}>
  <link rel="stylesheet" href="/feature.css" precedence="default" />
  <FeatureComponent />
</Suspense>

Custom Elements Support

React 19 adds full support for Custom Elements (Web Components).

// Props matching element properties are assigned as properties
// Others are assigned as attributes
<my-element
  stringAttr="hello"           // Attribute (string)
  complexProp={{ foo: 'bar' }} // Property (object)
  onCustomEvent={handleEvent}  // Property (function)
/>

Client-side: React checks if a property exists on the element instance. If yes, assigns as property; otherwise, as attribute.

Server-side (SSR): Primitive types (string, number) render as attributes. Objects, functions, symbols are omitted from HTML.

// Define custom element
class MyElement extends HTMLElement {
  constructor() {
    super();
    this.data = undefined; // React will assign to this property
  }

  connectedCallback() {
    this.textContent = JSON.stringify(this.data);
  }
}
customElements.define('my-element', MyElement);

// Use in React
<my-element data={{ items: [1, 2, 3] }} />

Hydration Improvements

Better Error Messages

React 19 shows a single error with a diff instead of multiple vague errors:

Uncaught Error: Hydration failed because the server rendered HTML
didn't match the client.

<App>
  <span>
+   Client
-   Server

Third-Party Script Compatibility

React 19 gracefully handles elements inserted by browser extensions or third-party scripts:

  • Unexpected tags in <head> and <body> are skipped (no mismatch errors)
  • Stylesheets from extensions are preserved during re-renders
  • No need to add suppressHydrationWarning for extension-injected content

Removed APIs (Breaking)

RemovedMigration
ReactDOM.render()createRoot().render()
ReactDOM.hydrate()hydrateRoot()
unmountComponentAtNode()root.unmount()
ReactDOM.findDOMNode()Use refs
propTypesTypeScript or remove
defaultProps (functions)ES6 default parameters
String refsCallback refs or useRef
Legacy ContextcreateContext
React.createFactoryJSX
react-dom/test-utilsact from 'react'

See references/deprecations.md for migration guides.

TypeScript Changes

// useRef requires argument
const ref = useRef<HTMLDivElement>(null); // Required
const ref = useRef(); // Error in React 19

// Ref callbacks must not return values (except cleanup)
<div ref={(node) => { instance = node; }} /> // Correct
<div ref={(node) => (instance = node)} />    // Error - implicit return

// ReactElement props are now unknown (not any)
type Props = ReactElement['props']; // unknown in R19, any in R18

// JSX namespace - import explicitly
import type { JSX } from 'react';

See references/typescript-changes.md for codemods.

Migration Codemods

# Run all React 19 codemods
npx codemod@latest react/19/migration-recipe

# Individual codemods
npx codemod@latest react/19/replace-reactdom-render
npx codemod@latest react/19/replace-string-ref
npx codemod@latest react/19/replace-act-import
npx codemod@latest react/19/replace-use-form-state
npx codemod@latest react/prop-types-typescript

# TypeScript types
npx types-react-codemod@latest preset-19 ./src

Imports (Best Practice)

// Named imports (recommended)
import { useState, useEffect, useRef, use } from 'react';
import { createRoot } from 'react-dom/client';
import { useFormStatus } from 'react-dom';

// Default import still works but named preferred
import React from 'react'; // Works but not recommended

Error Handling Changes

// React 19 error handling options
const root = createRoot(container, {
  onUncaughtError: (error, errorInfo) => {
    // Errors not caught by Error Boundary
    console.error('Uncaught:', error, errorInfo.componentStack);
  },
  onCaughtError: (error, errorInfo) => {
    // Errors caught by Error Boundary
    reportToAnalytics(error);
  },
  onRecoverableError: (error, errorInfo) => {
    // Errors React recovered from automatically
    console.warn('Recovered:', error);
  }
});

See references/suspense-streaming.md for Suspense patterns and error boundaries.

React 19.2+ Features

Activity Component (19.2)

Hide/show UI while preserving state (like background tabs):

import { Activity } from 'react';

// State preserved when hidden, Effects cleaned up
<Activity mode={isVisible ? 'visible' : 'hidden'}>
  <ExpensiveComponent />
</Activity>

useEffectEvent Hook (19.2)

Extract non-reactive logic from Effects without adding dependencies:

import { useEffect, useEffectEvent } from 'react';

function Chat({ roomId, theme }) {
  // Reads theme without making it a dependency
  const onConnected = useEffectEvent(() => {
    showNotification(`Connected!`, theme);
  });

  useEffect(() => {
    const conn = connect(roomId);
    conn.on('connected', onConnected);
    return () => conn.disconnect();
  }, [roomId]); // theme NOT in deps - won't reconnect on theme change
}

See references/react-19-2-features.md for complete 19.1+ and 19.2 features.

Reference Documentation

DocumentContent
paradigm-shifts.mdMental model changes - how to *think* in React 19
anti-patterns.mdWhat to stop doing - outdated patterns
react-19-2-features.mdReact 19.1+ and 19.2 features (Activity, useEffectEvent)
new-hooks.mdComplete API for 19.0 hooks
server-components.mdRSC, Server Actions, directives
suspense-streaming.mdSuspense, streaming, error handling
react-compiler.mdAutomatic memoization details
deprecations.mdRemoved APIs with migration guides
typescript-changes.mdType changes and codemods

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

OpenCode

32.12%
按下载量换算172

Claude Code

21.6%
按下载量换算116

Gemini CLI

19.71%
按下载量换算105

Antigravity

14.56%
按下载量换算78

Codex

7.22%
按下载量换算39

Cursor

3.41%
按下载量换算18

安全审计

暂无安全审计结果可展示。

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills