React 19 稳定版 All In One
React 19 稳定版 All In One
React 19 新功能
Actions
In React 19, we’re adding support for using async functions
in transitions
to handle pending states
, errors, forms, and optimistic updates automatically.
useTransition
// Using pending state from Actions
function UpdateName({}) {
const [name, setName] = useState("");
const [error, setError] = useState(null);
const [isPending, startTransition] = useTransition();
const handleSubmit = () => {
startTransition(async () => {
const error = await updateName(name);
if (error) {
setError(error);
return;
}
redirect("/path");
})
};
return (
<div>
<input value={name} onChange={(event) => setName(event.target.value)} />
<button onClick={handleSubmit} disabled={isPending}>
Update
</button>
{error && <p>{error}</p>}
</div>
);
}
old version useState
useState
// Before Actions
function UpdateName({}) {
const [name, setName] = useState("");
const [error, setError] = useState(null);
const [isPending, setIsPending] = useState(false);
const handleSubmit = async () => {
setIsPending(true);
const error = await updateName(name);
setIsPending(false);
if (error) {
setError(error);
return;
}
redirect("/path");
};
return (
<div>
<input value={name} onChange={(event) => setName(event.target.value)} />
<button onClick={handleSubmit} disabled={isPending}>
Update
</button>
{error && <p>{error}</p>}
</div>
);
}
New hook: useActionState
const [error, submitAction, isPending] = useActionState(
async (previousState, newName) => {
const error = await updateName(newName);
if (error) {
// You can return any result of the action.
// Here, we return only the error.
return error;
}
// handle success
return null;
},
null,
);
https://react.dev/reference/react/useActionState
https://react.dev/blog/2024/12/05/react-19#new-hook-useactionstate
React DOM: <form>
Actions
<form action={actionFunction}>
https://react.dev/reference/react-dom/components/form
https://react.dev/reference/react-dom/components/input
React DOM: New hook: useFormStatus
import {useFormStatus} from 'react-dom';
function DesignButton() {
const {pending} = useFormStatus();
return <button type="submit" disabled={pending} />
}
https://react.dev/reference/react-dom/hooks/useFormStatus
New hook: useOptimistic
function ChangeName({currentName, onUpdateName}) {
const [optimisticName, setOptimisticName] = useOptimistic(currentName);
const submitAction = async formData => {
const newName = formData.get("name");
setOptimisticName(newName);
const updatedName = await updateName(newName);
onUpdateName(updatedName);
};
return (
<form action={submitAction}>
<p>Your name is: {optimisticName}</p>
<p>
<label>Change Name:</label>
<input
type="text"
name="name"
disabled={currentName !== optimisticName}
/>
</p>
</form>
);
}
https://react.dev/reference/react/useOptimistic
New API: use
import {use} from 'react';
function Comments({commentsPromise}) {
// `use` will suspend until the promise resolves.
const comments = use(commentsPromise);
return comments.map(comment => <p key={comment.id}>{comment}</p>);
}
function Page({commentsPromise}) {
// When `use` suspends in Comments,
// this Suspense boundary will be shown.
return (
<Suspense fallback={<div>Loading...</div>}>
<Comments commentsPromise={commentsPromise} />
</Suspense>
)
}
use
does not support
promises created in render.
❌ A component was suspended by an uncached promise. Creating promises inside a Client Component or hook is not yet supported, except via a Suspense-compatible library or framework.
import {use} from 'react';
import ThemeContext from './ThemeContext'
function Heading({children}) {
if (children == null) {
return null;
}
// This would not work with useContext
// because of the early return.
const theme = use(ThemeContext);
return (
<h1 style={{color: theme.color}}>
{children}
</h1>
);
}
New React DOM Static APIs
https://react.dev/reference/react-dom/static
prerender
import { prerender } from 'react-dom/static';
async function handler(request) {
const {prelude} = await prerender(<App />, {
bootstrapScripts: ['/main.js']
});
return new Response(prelude, {
headers: { 'content-type': 'text/html' },
});
}
https://react.dev/reference/react-dom/static/prerender
prerenderToNodeStream
https://react.dev/reference/react-dom/static/prerenderToNodeStream
React Server Components
https://react.dev/reference/react-dom/server
Server Components
https://react.dev/reference/rsc/server-components
Server Actions
https://react.dev/reference/rsc/server-actions
React 19 中的改进
ref
as a prop
function MyInput({placeholder, ref}) {
return <input placeholder={placeholder} ref={ref} />
}
//...
<MyInput ref={ref} />
Diffs for hydration errors
<Context>
as a provider
In React 19, you can render <Context>
as a provider instead of <Context.Provider>
:
const ThemeContext = createContext('');
function App({children}) {
return (
<ThemeContext value="dark">
{children}
</ThemeContext>
);
}
Cleanup functions for refs
<input
ref={(ref) => {
// ref created
// NEW: return a cleanup function to reset the ref when element is removed from DOM.
return () => {
// ref cleanup
};
}}
/>
TypeScript
- <div ref={current => (instance = current)} />
+ <div ref={current => {instance = current}} />
https://github.com/eps1lon/types-react-codemod/#no-implicit-ref-callback-return
useDeferredValue
initial value
function Search({deferredValue}) {
// On initial render the value is ''.
// Then a re-render is scheduled with the deferredValue.
const value = useDeferredValue(deferredValue, '');
return (
<Results query={value} />
);
}
https://react.dev/reference/react/useDeferredValue
Support for Document Metadata
In React 19, we’re adding support for rendering document metadata tags in components natively:
function BlogPost({post}) {
return (
<article>
<h1>{post.title}</h1>
<title>{post.title}</title>
<meta name="author" content="Josh" />
<link rel="author" href="https://twitter.com/joshcstory/" />
<meta name="keywords" content={post.keywords} />
<p>
Eee equals em-see-squared...
</p>
</article>
);
}
https://react.dev/reference/react-dom/components/meta
https://react.dev/reference/react-dom/components/title
https://react.dev/reference/react-dom/components/link
Support for stylesheets
function ComponentOne() {
return (
<Suspense fallback="loading...">
<link rel="stylesheet" href="foo" precedence="default" />
<link rel="stylesheet" href="bar" precedence="high" />
<article class="foo-class bar-class">
{...}
</article>
</Suspense>
)
}
function ComponentTwo() {
return (
<div>
<p>{...}</p>
<link rel="stylesheet" href="baz" precedence="default" /> <-- will be inserted between foo & bar
</div>
)
}
function App() {
return <>
<ComponentOne />
...
<ComponentOne /> // won't lead to a duplicate stylesheet link in the DOM
</>
}
https://react.dev/reference/react-dom/components/style
Support for async scripts
function MyComponent() {
return (
<div>
<script async={true} src="..." />
Hello World
</div>
)
}
function App() {
<html>
<body>
<MyComponent>
...
<MyComponent> // won't lead to duplicate script in the DOM
</body>
</html>
}
https://react.dev/reference/react-dom/components/script
Support for preloading resources
import { prefetchDNS, preconnect, preload, preinit } from 'react-dom'
function MyComponent() {
preinit('https://.../path/to/some/script.js', {as: 'script' }) // loads and executes this script eagerly
preload('https://.../path/to/font.woff', { as: 'font' }) // preloads this font
preload('https://.../path/to/stylesheet.css', { as: 'style' }) // preloads this stylesheet
prefetchDNS('https://...') // when you may not actually request anything from this host
preconnect('https://...') // when you will request something but aren't sure what
}
<!-- the above would result in the following DOM/HTML -->
<html>
<head>
<!-- links/scripts are prioritized by their utility to early loading, not call order -->
<link rel="prefetch-dns" href="https://...">
<link rel="preconnect" href="https://...">
<link rel="preload" as="font" href="https://.../path/to/font.woff">
<link rel="preload" as="style" href="https://.../path/to/stylesheet.css">
<script async="" src="https://.../path/to/some/script.js"></script>
</head>
<body>
...
</body>
</html>
https://react.dev/reference/react-dom#resource-preloading-apis
Compatibility with third-party
scripts and extensions
Better error reporting
https://react.dev/reference/react-dom/client/createRoot
https://react.dev/reference/react-dom/client/hydrateRoot
Support for Custom Elements
https://custom-elements-everywhere.com/
demos
React 19 Upgrade Guide
https://react.dev/blog/2024/04/25/react-19-upgrade-guide
refs
https://react.dev/blog/2024/12/05/react-19
©xgqfrms 2012-2025
www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!
原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!
本文首发于博客园,作者:xgqfrms,原文链接:https://www.cnblogs.com/xgqfrms/p/18593035
未经授权禁止转载,违者必究!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
2022-12-08 ESM & import() & dynamic import All In One
2022-12-08 how to import a CommonJS module as an ECMAScript module All In One
2022-12-08 How to fix MongoDB warnings All In One
2022-12-08 macOS login items & background process All In One
2021-12-08 React Conf 2021 All In One
2020-12-08 npm Fetch package All In One
2020-12-08 DNS & HTTPS bug