【前端风向标】第二期-React 19 新特性洞察

作者:黄轩 openInula核心贡献者/架构SIG成员

新增

use

use作为React19更新感知最明显的变化,其主要作用是获取异步数据,use可以用来读取context,promise对象。且与Hooks不同,use可以被有条件地调用 。React社区未来计划支持在渲染中使用use的更多方式

tsx 复制代码
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不支持在渲染中创建的Promise

tsx 复制代码
function Comments({commentsPromise}) {
	const fetchData = new Promise<string>(resolve => setTimeout(() => resolve('Hello React19')));
	const comments = use(commentsPromise);
	return comments.map(comment => <p key={comment.id}>{comment}</p>);
}

useOptimistic

乐观更新

是一种在用户界面(UI)和数据交互场景中使用的策略,主要用于提升用户体验。在许多应用程序中,当用户执行一个操作(如提交表单、添加或删除数据项等)时,通常需要向服务器发送请求来更新数据。传统的方式是等待服务器响应后再更新 UI。而乐观更新则是在发送请求的同时,假设服务器会成功处理这个请求,立即更新 UI 来反映这个变化。

使用场景
  • 购物车应用添加商品:用户将商品添加到购物车时,购物车中的商品数量和总价会立刻更新,好像商品已经成功添加到购物车一样。随后服务器会验证这个添加操作是否合法(例如商品是否有库存、用户是否登录等)。如果服务器验证成功,这个更新就保持;如果失败,购物车的数量和总价会回滚到之前的状态。
  • 即使通讯软件中发送消息:当用户发送一条消息时,消息会立即出现在聊天窗口的发送框下方,并且显示为 "已发送" 状态。这是一种乐观更新,因为软件假设消息能够成功发送到服务器并被接收方获取。
示例
tsx 复制代码
function Thread({ messages, sendMessage }) {
  const formRef = useRef();
  async function formAction(formData) {
    addOptimisticMessage(formData.get("message"));
    formRef.current.reset();
    await sendMessage(formData);
  }
  const [optimisticMessages, addOptimisticMessage] = useOptimistic(
    messages,
    (state, newMessage) => [
      ...state,
      {
        text: newMessage,
        sending: true
      }
    ]
  );

  return (
    <>
      {optimisticMessages.map((message, index) => (
        <div key={index}>
          {message.text}
          {!!message.sending && <small> (Sending...)</small>}
        </div>
      ))}
      <form action={formAction} ref={formRef}>
        <input type="text" name="message" placeholder="Hello!" />
        <button type="submit">Send</button>
      </form>
    </>
  );
}

export default function App() {
  const [messages, setMessages] = useState([
    { text: "Hello there!", sending: false, key: 1 }
  ]);
  async function sendMessage(formData) {
    const sentMessage = await deliverMessage(formData.get("message"));
    setMessages((messages) => [...messages, { text: sentMessage }]);
  }
  return <Thread messages={messages} sendMessage={sendMessage} />;
}

当请求完成后optimisticMessages的值会被更新为messages,请求失败时optimisticMessages会回退到未更新的messages

useActionState

useActionState 是一个可以根据某个表单动作的结果更新 state 的 Hook,返回的action需要在<form>标签中触发

tsx 复制代码
async function add(payload: { value: number }) {
  return new Promise<{ value: number }>(resolve => {
    setTimeout(() => {
      resolve({ value: payload.value + 1 });
    }, 2000);
  });
}

function useActionStateDemo() {
  const [state, action, isPending] = useActionState<{ value: number }>(add, { value: 0 });

  return (
    <form>
      {isPending ? 'working' : <div>{state.value}</div>}
      <button formAction={action}>plus value</button>
    </form>
  );
}

注意 该Hook在React19 RC中的名称为useFormState

变更

ref

refprop支持传入清理函数,当组件卸载时,React 将调用从 ref 回调返回的清理函数。这适用于 DOM refs,类组件的 refs,以及 useImperativeHandle

tsx 复制代码
<input ref={(ref)=>{ 
	// xxx
	return ()=>{
		// ref clean
	}
}}>

注意 在React19之前的版本,卸载组件时ref会被置为null,现在如果提供了清理函数,React将不再会将ref置为null

注意:Ref函数中的隐式返回可能导致问题

diff 复制代码
- <div ref={current => (instance = current)} />
+ <div ref={current => {instance = current}} />

Context

<Context>可以直接作为渲染提供者,无需使用<Context.Provider> 在未来的版本中会废弃<Context.Provider>的写法

forwardRef

React19中函数式组件可以直接使用Ref,不再需要forwardRef函数

  • Befor
tsx 复制代码
const MyInput = forwardRef(function ({ placeholder }, ref) {
  return <input placeholder={placeholder} ref={ref} />;
});
  • Now
tsx 复制代码
const MyInput = ({placeholder, ref}) => {
	return <input placeholder={placeholder} ref={ref}>
}

在未来的版本中forwardRef函数会废弃

useDeferredValue

React19支持useDeferredValue传入第二个参数initialValue,函数签名如下

typescript 复制代码
export function useDeferredValue<T>(value: T, initialValue?: T): T;

使用该参数useDeferredValue在首次渲染就可以延迟

useTransition

useTransition支持异步函数

await之后的状态不会视为Transition

tsx 复制代码
startTransition(async () => {
	await someAsyncFunction();
	// ❌ 不要在 await 之后调用 startTransition
	setPage('/about');
});
tsx 复制代码
startTransition(async () => {
	await someAsyncFunction();
	// ✅ await之后再使用Transition
	startTransition(() => {
		setPage('/about');
	});
});

移除

  • string Refs
  • getChildContextcontextTypes

ReactDOM

新增

<form> Action

在 React 19 中,Actions 与 react-dom 的新 <form> 特性进行了整合。现在,可以将函数作为<form><input><button>元素的action和formAction属性,以便自动使用 Actions 提交表单:

tsx 复制代码
<input action={action}/>

<form>的action成功执行时,React会自动为不受控组件重置表单状态。如果需要手动重置<form>,React DOM API 提供了全新的requestFormReset方法。

useFormStatus

用于获取上次表单提交状态信息 const { pending, data, method, action } = useFormStatus();

  • pending:布尔值。如果为 true,则表示父级 <form> 正在等待提交;否则为 false

  • data:实现了 FormData interface 的对象,包含父级 <form> 正在提交的数据;如果没有进行提交或没有父级 <form>,它将为 null

  • method:字符串,可以是 'get''post'。表示父级 <form> 使用 GETPOST HTTP 方法 进行提交。默认情况下,<form> 将使用 GET 方法,并可以通过 method 属性指定。

  • action:一个传递给父级 <form>action 属性的函数引用。如果没有父级 <form>,则该属性为 null。如果在 action 属性上提供了 URI 值,或者未指定 action 属性,status.action 将为 null

注意 该Hook只能在位于<form>标签之下的函数式组件中使用

移除

  • unmountComponentAtNode
  • ReactDOM.findDOMNode
  • ReactDOM.render
  • ReactDOM.hydrate
相关推荐
梦想平凡10 分钟前
开元类双端互动组件部署实战全流程教程(第1部分:环境与搭建)
运维·服务器·前端·游戏·node.js
HelloRevit21 分钟前
React -> AI组件 -> 调用Ollama模型, qwen3:1.7B非常聪明
前端·react.js·前端框架
geovindu27 分钟前
javascript: Multi-page PDF in Canvas using PDFJS 5.1
前端·javascript
暮 夏31 分钟前
利用session在html和MySQL实现登录
前端·mysql·html
吃面必吃蒜42 分钟前
前端实战中的单例模式:以医疗药敏管理为例
前端·javascript·单例模式·设计模式
哎哟喂_!1 小时前
Node.js vs 浏览器中的JavaScript:区别全解析
开发语言·javascript·node.js
陈奕昆1 小时前
二、【LLaMA-Factory实战】数据工程全流程:从格式规范到高质量数据集构建
前端·人工智能·python·llama·大模型微调
迷茫运维路1 小时前
《企业级前端部署方案:Jenkins+MinIO+SSH+Gitee+Jenkinsfile自动化实践》
运维·前端·gitee·自动化·ssh·jenkins
溟洵1 小时前
【C++ Qt】多元素控件(ListWidget、TableWidget、TreeWidget)
开发语言·前端·c++·后端·qt
1nv1s1ble1 小时前
React 笔记[1] hello world
前端·笔记·react.js