零、前言
React 官方将于 2024 年 5月15-16号正式发布 19 版本!
自从上一次React更新(v18.2版本)发布以来已经过去了超过600天,这段时间里React团队一直在进行哪些工作,一直是React社区感到好奇的一个话题。今天,我们就来揭秘一下React团队在这段时间内做出的研究成果,看看他们是如何默默努力的,为我们带来更多的创新和突破。
一、再次赋能 Hook
React 作为主流的前端框架,一直以灵活、可封装性著称,大家也常常把 React 比做手动挡,Vue比做自动挡。
从 v16.8 版本引入全新的 API -- React Hooks,颠覆了以前的用法。如今 Hook 已经是 React 最大的卖点了,而接下来的 19 版本 React 又推出了新的 Hook ,我们下面来一起看看吧。
1.1 useFormStatus
useFormStatus
是一个状态钩子,它为我们提供上次表单的状态信息。
js
import { useFormState } from "react-dom";
async function increment(previousState, formData) {
return previousState + 1;
}
function StatefulForm({}) {
const [state, formAction] = useFormState(increment, 0);
return (
<form>
{state}
<button formAction={formAction}>Increment</button>
</form>
)
}
上面代码中,useFormState
接收两个参数 fn
和 initialState
, 返回当前表单的状态和操作函数。
fn
:调用返回值formAction
触发,接收表单的前一个状态,和表单当前的状态。initialState
: 表单的初始状态。- 可选参数
permalink
: 表示表单提交后需要跳转的 URL,默认是当前页面。
返回值两个值的数组:
state
: 当前状态。formAction
: 传递给表单的动作。
1.2 useFormState()
useFormStatus
钩子提供最后一次表单提交的状态信息。
js
import { useFormStatus } from "react-dom";
import action from './actions';
function Submit() {
const status = useFormStatus();
return <button disabled={status.pending}>Submit</button>
}
export default function App() {
return (
<form action={action}>
<Submit />
</form>
);
}
useFormStatus
不用接收任何参数,返回一个状态对象,包含以下属性:
-
pending
:一个布尔值。如果为true,表示父级<form>
正在等待提交。否则为false。 -
data
:一个实现了FormData接口的对象,包含父级<form>
要提交的数据。如果没有父级<form>
,它将为null。 -
method
:一个字符串值,可以是'get'或'post'。表示父级<form>
是使用GET还是POST HTTP方法进行提交。默认情况下,<form>
将使用GET方法,并可以通过method属性进行指定。 -
action
:对应于父级<form>
的action属性传递的函数的引用。如果没有父级<form>
,该属性为null。如果action属性提供了URI值,或者没有指定action属性,则status.action将为null。
1.3 useOptimistic()
useOptimistic
,它旨在简化乐观更新的实现。
使用useOptimistic Hook,开发人员只需提供当前状态和一个更新函数,就可以获得乐观状态的副本。在异步操作期间,React会自动渲染这个乐观状态,以提供即时的用户反馈。当异步操作完成后,React会根据实际结果更新UI,以确保最终状态的一致性。这个新的Hook可以帮助开发人员更轻松地处理乐观更新的情况,提高开发效率和用户体验。
使用示例:
js
import { useOptimistic } from 'react';
function LikeButton({ postId, initialLikes }) {
const [likes, setLikes] = useState(initialLikes);
const [optimisticLikes, updateOptimisticLikes] = useOptimistic(
likes,
(currentLikes, isLiked) => (isLiked ? currentLikes + 1 : currentLikes - 1)
);
const handleLike = async () => {
updateOptimisticLikes(!optimisticLikes > likes);
try {
await likePost(postId);
setLikes(optimisticLikes);
} catch (error) {
setLikes(likes);
}
};
return (
<button onClick={handleLike}>
{optimisticLikes} Likes
</button>
);
}
二、全新编译器:自动记忆化
过去,开发人员想要优化 React 重复渲染的问题,通常需要手动使用 useMemo
、 useCallback
和 memo
等AAPI来优化组件等渲染性能。
使用示例:
js
import React, { useMemo } from 'react';
function ExpensiveComponent(props) {
const value = useMemo(() => {
// 执行一些昂贵的计算
return someExpensiveComputation(props.data);
}, [props.data]);
return <div>{value}</div>;
}
React 19 引入了新的革命性的自动化记忆化功能,打破这一繁琐的优化,降低了开发人员的心智负担。
通过全新编译器,React 19 可以自动检测组件的状态变化,并智能地决定是否要重新渲染。
这种方式已经在 instagram.com 成功交付。
三、其他新特性
除了上述革命性的新特性之外,React 19还包含了一系列其他值得关注的更新:
3.1 use client 与 use server
随着全栈框架 Next
、Nuxt
等的兴起,前端开发已经不是简单的客户端页面,React 19 引入了 use client
和 use server
,旨在帮助开发人员更好地管理客户端和服务端代码。
use client
指示打包工具生成一个<script>
标签,用于运行客户端代码。而use server
则告诉打包工具生成一个POST端点,用于运行服务端代码。有趣的是,这两个指令允许开发者在同一个文件中编写客户端和服务端代码,极大地简化了全栈开发的工作流程。以下是一个使用这两个指令的示例:
js
// app/page.jsx
import React from 'react';
import { use } from 'react';
// 服务端代码
const getData = use(async () => {
const res = await fetch('https://api.example.com/data');
return res.json();
});
export default function Page() {
// 客户端代码
const [count, setCount] = React.useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
<pre>{JSON.stringify(getData, null, 2)}</pre>
</div>
);
}
3.2 文档元数据
React 19 添加了在组件树中任意位置呈现的 <title>
、 <meta>
、 <link>
等标签的内置支持。
这些在所有环境中都以相同的方式工作,包括完全客户端代码、SSR和RSC。这为React Helmet等库开创的功能提供了内置支持。
3.3 资源加载
React 19 将Suspense与样式表、字体和脚本等资源的加载生命周期集成在一起,以便React将其考虑在内,以确定<style>
、<link>
和<script>
等元素中的内容是否已准备好显示。
还新增了新的 API,如预请求、预加载。原文链接
引入这些 API ,我们可以更好的控制资源的加载和初始化。
总结
随着越来越多的人开始使用 React 19,我们可以预期将会看到更多功能强大和互动性更高的网站和应用程序出现。React 19 的发布将是一个里程碑,为前端开发的未来趋势和创新奠定了基础。