🌟 React v19 中的新功能 – 概述
以下是 React 19 将具有的新功能的快速概述:
- 🤖 React 编译器:React 正在致力于实现一个新的编译器。目前,Instagram 已经在利用这项技术,并将在未来版本的 React 中发布。
- 🔥服务器组件:React 经过多年的发展引入了服务器组件的概念。您现在可以在 Next.js 中使用此功能。
- 💪Action:动作也将彻底改变我们与 DOM 元素交互的方式。
- 🌇文档元数据:另一个急需的改进即将到来,使开发人员能够用更少的代码完成更多的工作。
- 💼资产加载:这将使资产在后台加载,这将改善应用程序的加载时间和用户体验。
- ⚙️ Web 组件:这特别令人着迷:React 代码现在使我们能够合并 Web 组件。我对这一发展感到非常兴奋,因为它将释放无数的可能性。
- 🪝增强的钩子:令人兴奋的新钩子即将出现,有望彻底改变我们的编码体验。
React 19 旨在解决 React 长期面临的挑战之一:过度重新渲染的问题。
以前,开发人员依靠useMemo()
、useCallback()
、memo
等技术来管理重新渲染。但在 React 19 中,这种手动干预将不再是必要的。
1. 🤖 🤖 React 编译器 🤖 🤖
目前,React 不会在状态更改时自动重新渲染。优化这些重新渲染的一种方法是手动使用useMemo()
、useCallback()
和memo
API。根据 React 团队的说法,这是“合理的手动妥协”。他们的愿景是让 React 管理这些重新渲染。
但React团队意识到手动优化很麻烦,社区的反馈鼓励他们解决这个问题。
因此,React 团队创建了“React 编译器”。 React 编译器现在将管理这些重新渲染。 React 将自动决定如何以及何时更改状态并更新 UI。
有了这个,我们开发人员就不再需要手动执行此操作了。这也意味着不需要使用useMemo()
、、useCallback()
和memo
。
这将在即将发布的 React 版本中发布.
因此,React 将决定优化哪些组件以及何时优化,以及重新渲染哪些内容。
我喜欢 React 的一件事是,在向外部世界引入新的突破性变化之前,React 团队首先在他们的生产产品上使用这些新功能😍。目前,React Compiler 正在为Instagram 的生产环境提供支持。
2. 🔥🔥 服务器组件 🔥🔥
如果您还没有听说过服务器组件,那么您就错过了 React 和 Next.js 中最令人兴奋的开发之一。
到目前为止,React 组件主要运行在客户端。但 React 引入了在服务器端运行组件的突破性概念。
服务器组件的想法已经流传多年,Next.js 是在生产中实现它们的先驱。从 Next.js 13 开始,所有组件默认都是服务器组件。要使组件在客户端运行,您需要使用“use client”指令。
在 React 19 中,服务器组件将直接集成到 React 中,带来许多优势:
- SEO:服务器渲染组件通过为网络爬虫提供更易于访问的内容来增强搜索引擎优化。
- 性能提升:服务器组件有助于加快初始页面加载速度并提高整体性能,特别是对于内容较多的应用程序。
- 服务器端执行:服务器组件支持在服务器上执行代码,使 API 调用等任务无缝且高效。
这些优势凸显了服务器组件在现代 Web 开发中的变革潜力。
React 中的所有组件默认都是客户端。只有当你使用时,'use server'
该组件才是服务器组件。
以下代码位于 React 中,但将在服务器上运行。您只需添加'use server'
为组件的第一行。这将使该组件成为“服务器组件”。它不会在客户端运行,只会在服务器端运行。
那么如何使用服务器组件呢?
我们可以导入requestUsername
同一项目中的任何 React 组件。在任何 React 组件中导入服务器组件后,我们可以使用“Actions”(我们很快就会了解这一点)来执行特定任务。
'use server';
export default async function requestUsername(formData) {
const username = formData.get('username');
if (canRequest(username)) {
// ...
return 'successful';
}
return 'failed';
}
在“操作”部分中,您将了解有关如何使用服务器组件的更多信息。
目前 Next.js 具有服务器端组件支持。您可以在此处的“下一步”中阅读有关服务器组件的更多信息。在 React19 中,服务器组件支持将直接在 React 中提供。
3. 💪💪 Actions 💪💪
在版本 19 中,另一个令人兴奋的新增功能是Actions。这将彻底改变我们使用表单的方式。 Actions 允许您将Actions与 HTML中form集成。简而言之,您将能够用Actions替换 onSubmit事件。这些Actions是 HTML表单属性。
Before Actions:
在下面的代码片段中,我们将利用 onSubmit
React 事件,该事件在表单提交时触发 search
方法的执行。但需要注意的是,目前 search
方法仅在客户端运行。我们仅限于使用 React 事件进行表单提交,这意味着 search
无法在服务器端执行。
<form onSubmit={search}>
<input name="query" />
<button type="submit">Search</button>
</form>
After Actions:
随着服务器组件的引入,Actions可以在服务器端执行。在我们的 JSX 中,通过
,我们可以删除 事件并使用属性。 action 属性的值将是在客户端或服务器端提交数据的方法。 您可以使用操作执行同步和异步操作,从而简化数据提交管理和状态更新。目标是使表单的使用和数据的处理变得更加容易。 让我们看一个例子来看看它是如何工作的:"use server"
const submitData = async (userData) => {
const newUser = {
username: userData.get('username'),
email: userData.get('email')
}
console.log(newUser)
}
const Form = () => {
return <form action={submitData}>
<div>
<label>Name</label>
<input type="text" name='username'/>
</div>
<div>
<label>Name</label>
<input type="text" name="email" />
</div>
<button type='submit'>Submit</button>
</form>
}
export default Form;
在上面的代码中, submitData
是服务器组件中的操作。 form
是一个客户端组件,它使用 submitData
作为Action。 submitData
将在服务器上执行。客户端 ( form
) 和服务器 ( submitData
) 组件的通信只能通过 action
属性实现。
我们可以使用表单和操作来处理客户端和服务器端的数据提交
在“增强hook”部分中,您将学习三个新hook,它们也将增强您使用表单的方式。
4. ⚙️⚙️网络组件⚙️⚙️
大约 5 年前,我深入研究了Web 组件的世界。从那时起,我就被他们的潜力所吸引。如果你不熟悉 Web 组件,让我为你分解一下:
Web 组件允许您使用本机 HTML、CSS 和 JavaScript 创建自定义组件,将它们无缝地合并到您的 Web 应用程序中,就像它们是标准 HTML 标签一样。非常神奇,对吧?
目前,将 Web 组件集成到 React 中并不简单。通常,您需要将 Web 组件转换为 React 组件,或者安装额外的包并编写额外的代码以使 Web 组件与 React 一起使用。这可能会令人沮丧。
幸运的是,React 19 将帮助您更轻松地将 Web 组件集成到 React 代码中。如果您遇到一个真正有用的 Web 组件,例如轮播,您可以将其无缝地合并到您的 React 项目中,而无需将其转换为 React 代码。
这简化了开发,并允许您在 React 应用程序中利用现有 Web 组件的庞大生态系统。
但到目前为止,还没有关于代码外观的更多细节。尽管如此,我还是希望它能简单地将 Web 组件导入到 React 代码库中,类似于模块联合。我热切地等待 React 团队提供有关此实现的更多细节。
5. 🌇🌇文档元数据🌇🌇
“标题”、“元标签”和“描述”等元素对于优化 SEO 和确保可访问性至关重要。在单页应用程序盛行的 React 中,跨不同路由管理这些元素可能会有点麻烦。
目前,开发人员经常求助于编写自定义代码,或使用像react-helmet这样的包来处理路线更改并相应地更新元数据。此过程可能重复且容易出错,尤其是在处理元标记等 SEO 敏感元素时。
前:
import React, { useEffect } from 'react';
const HeadDocument = ({ title }) => {
useEffect(() => {
document.title = title;
const metaDescriptionTag = document.querySelector('meta[name="description"]');
if (metaDescriptionTag) {
metaDescriptionTag.setAttribute('content', 'New description');
}
}, [title]);
return null;
};
export default HeadDocument;
在上面的代码中,我们有一个组件HeadDocument
负责title
根据meta
.props
我们正在useEffect
挂钩中更新这些。我们还使用 JavaScript 来更新标题和元标记。该组件将在路线更改时更新。这不是一个干净的方法。
后:
使用 React19,我们可以直接在 React 组件中使用title
和标签:meta
Const HomePage = () => {
return (
<>
<title>Freecodecamp</title>
<meta name="description" content="Freecode camp blogs" />
// Page content
</>
);
}
这在以前的 React 中是不可能的。唯一的方法是使用像react-helmet这样的包。
👉 您可以在这些资源中阅读有关链接、元、脚本、样式和标题的更多信息。
6.💼💼资产加载💼💼
在 React 中,您需要仔细管理应用程序的加载体验和性能,尤其是图像和其他资源文件。
通常,视图首先在浏览器中呈现,然后是样式表、字体和图像。这可能会导致从无样式(或无样式内容的闪烁)到样式视图的闪烁。
为了缓解这个问题,开发人员通常会添加自定义代码来检测这些资源何时准备就绪,确保仅在所有内容加载后才显示视图。
在 React 19 中,当用户浏览当前页面时,图像和其他文件将在后台加载。此改进应有助于缩短页面加载时间并减少等待时间。
此外,React 还引入了生命周期 Suspense 来加载资源,包括脚本、样式表和字体。此功能使 React 能够确定内容何时准备好显示,从而消除任何“无样式”闪烁。
有新的资源加载 API,例如preload
和 ,preinit
可以更好地控制资源何时加载和初始化。
通过允许资产在后台异步加载,React 19 最大限度地减少了等待时间,并确保用户可以不间断地与内容交互。这种优化不仅增强了 React 应用程序的性能,还有助于为用户带来更愉快的浏览体验。
7. 🪝🪝 新的 React Hook 🪝🪝
React Hooks 是该库中最受欢迎的功能之一。您可能多次使用过 React 的内置钩子,也许您也尝试过制作自己的自定义钩子。 Hooks 非常流行,以至于它们已经成为一种 React 编程模式。
在 React 19 中,我们使用useMemo
、forwardRef
、useEffect
和 的方式useContext
将会改变。这主要是因为use
将引入一个新的钩子 。
🥁 useMemo()
:
React19 之后你不需要使用useMemo()
钩子,因为 React Compiler 会自行记忆。
前:
import React, { useState, useMemo } from 'react';
function ExampleComponent() {
const [inputValue, setInputValue] = useState('');
// Memoize the result of checking if the input value is empty
const isInputEmpty = useMemo(() => {
console.log('Checking if input is empty...');
return inputValue.trim() === '';
}, [inputValue]);
return (
<div>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="Type something..."
/>
<p>{isInputEmpty ? 'Input is empty' : 'Input is not empty'}</p>
</div>
);
}
export default ExampleComponent;
后:
在下面的示例中,您可以看到在 React19 之后,我们不需要记住这些值 - React19 会在幕后自行完成。代码更加清晰:
import React, { useState, useMemo } from 'react';
function ExampleComponent() {
const [inputValue, setInputValue] = useState('');
const isInputEmpty = () => {
console.log('Checking if input is empty...');
return inputValue.trim() === '';
});
return (
<div>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="Type something..."
/>
<p>{isInputEmpty ? 'Input is empty' : 'Input is not empty'}</p>
</div>
);
}
export default ExampleComponent;
🥁forwardRef()
ref
现在将作为 props 传递,而不是使用forwardRef()
hook。这将简化代码。所以在 React19 之后,你将不再需要使用forwardRef()
.
前:
forwardRef()
以下是React 19 之前如何使用的示例:
import React, { forwardRef } from 'react';
const ExampleButton = forwardRef((props, ref) => (
<button ref={ref}>
{props.children}
</button>
));
后:
ref
可以作为 prop 传递。不再需要 forwardRef()
。
import React from 'react';
const ExampleButton = ({ ref, children }) => (
<button ref={ref}>
{children}
</button>
);
🥁 新use()
钩子
React19 将引入一个名为 的新钩子use()
。这个钩子将简化我们使用 Promise、异步代码和上下文的方式。
这是钩子的语法:
const value = use(resource);
下面的代码是如何使用钩子use
发出请求的示例fetch
:
import { use } from "react";
const fetchUsers = async () => {
const res = await fetch('https://jsonplaceholder.typicode.com/users');
return res.json();
};
const UsersItems = () => {
const users = use(fetchUsers());
return (
<ul>
{users.map((user) => (
<div key={user.id} className='bg-blue-50 shadow-md p-4 my-6 rounded-lg'>
<h2 className='text-xl font-bold'>{user.name}</h2>
<p>{user.email}</p>
</div>
))}
</ul>
);
};
export default UsersItems;
我们来理解一下代码:
fetchUsers
负责 GET 请求。- 我们使用
use
钩子来执行fetchUsers
而不是使用useEffect
或useState
钩子。 useState
钩子的返回users
将具有 GET 请求的响应 (users
)。- 在返回块中,我们使用
users
映射它并创建列表。
我们可以使用新钩子的另一个地方是 Context。 Context API 是一种在 React 中管理全局状态的流行方法,无需使用任何状态管理库。使用use
钩子后,context
钩子将类似于以下代码。
现在,我们将使用 use(context)
代替 useContext()
import { createContext, useState, use } from 'react';
const ThemeContext = createContext();
const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme((prevTheme) => (prevTheme === 'light' ? 'dark' : 'light'));
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
};
const Card = () => {
// use Hook()
const { theme, toggleTheme } = use(ThemeContext);
return (
<div
className={`p-4 rounded-md ${
theme === 'light' ? 'bg-white' : 'bg-gray-800'
}`}
>
<h1
className={`my-4 text-xl ${
theme === 'light' ? 'text-gray-800' : 'text-white'
}`}
>
Theme Card
</h1>
<p className={theme === 'light' ? 'text-gray-800' : 'text-white'}>
Hello!! use() hook
</p>
<button
onClick={toggleTheme}
className='bg-blue-500 hover:bg-blue-600 text-white rounded-md mt-4 p-4'
>
{theme === 'light' ? 'Switch to Dark Mode' : 'Switch to Light Mode'}
</button>
</div>
);
};
const Theme = () => {
return (
<ThemeProvider>
<Card />
</ThemeProvider>
);
};
export default Theme
我们来理解一下代码:
ThemeProvider
负责提供上下文。card
是我们将使用上下文的组件。为此,我们将使用新的钩子use
来使用上下文。其余与React19之前相同。
在 React19 中,我们还有新的钩子来处理表单状态和数据。这将使表单的使用更加顺畅和容易。将这些钩子与action
结合起来将使表单和数据处理变得更加容易。
🥁useFormStatus()
钩子
React19 中的这个新钩子将帮助您更好地控制您创建的表单。它将为您提供有关上次表单提交的状态信息。
语法如下:
const { pending, data, method, action } = useFormStatus();
或简单版本:
const { status } = useFormStatus()
让我们看看这里发生了什么:
- 待处理:如果表单处于待处理状态,则为
true
,否则为false
。 - data
FormData interface
:实现包含父级正在提交的数据的对象。 - method : HTTP 方法 –
GET
, 或POST
.默认情况下它将是GET
. - action:函数引用。
该挂钩将用于显示待处理状态以及用户正在提交哪些数据。
这是一个代码示例:
import { useFormStatus } from "react-dom";
function Submit() {
const status = useFormStatus();
return <button disabled={status.pending}>{status.pending ? 'Submitting...' : 'Submit'}</button>;
}
const formAction = async () => {
// Simulate a delay of 2 seconds
await new Promise((resolve) => setTimeout(resolve, 3000));
}
const FormStatus = () => {
return (
<form action={formAction}>
<Submit />
</form>
);
};
export default FormStatus;
让我们了解一下上面的代码中发生了什么:
Submit
是一种方法——表单提交表单的操作。此方法将检查 ,status
从中useFormStatus
让我们知道是status.pending
真还是假。- 基于此
status.pending
我们可以在UI中显示消息。 formAction
是一种延迟表单提交的伪造方法。
在上面的代码中,在表单提交时,useFormStatus
我们将从钩子中获取pending
状态。当待处理为 true 时,文本“正在提交...”将显示在 UI 上。一旦pending
,false
提交文本将更改为“已提交”。
这个钩子功能强大,当您想了解表单提交的状态(待处理或未处理)并相应地显示数据时,它会很有帮助。
🥁useFormState()
钩子
React19 中的另一个新钩子是useFormState
.它允许您根据表单提交的结果更新状态。
语法如下:
const [state, formAction] = useFormState(fn, initialState, permalink?);
fn
:提交表单或按下按钮时调用的函数。initialState
:您希望状态最初的值。它可以是任何可序列化的值。首次调用操作后,该参数将被忽略。permalink
: 这是可选的。 URL 或页面链接,如果fn
要在服务器上运行,则页面将重定向到permalink
.
该钩子将返回:
state
:初始状态将是我们传递给 的值initialState
。formAction
:将传递给表单操作的操作。它的返回值将在状态中可用。
以下是其工作原理的示例:
import { useFormState} from 'react-dom';
const FormState = () => {
const submitForm = (prevState, queryData) => {
const name = queryData.get("username");
console.log(prevState); // previous form state
if(name === 'john'){
return {
success: true,
text: "Welcome"
}
}
else{
return {
success: false,
text: "Error"
}
}
}
const [ message, formAction ] = useFormState(submitForm, null)
return <form action={formAction}>
<label>Name</label>
<input type="text" name="username" />
<button>Submit</button>
{message && <h1>{message.text}</h1>}
</form>
}
export default FormState;
让我们了解一下上面的代码中发生了什么:
submitForm
是负责表单提交的方法。这就是 Action(记住 Action 新的 React19 功能)。- 在内部
submitForm
,我们正在检查表单的值。然后,根据它是成功还是显示错误,我们返回特定的值和消息。在上面的代码示例中,如果存在“John”以外的任何值,那么它将返回错误。 - 我们还可以检查
prevState
表格的内容。初始状态为null
,之后它将返回prevState
表单的 。
运行此示例时,如果名称是 John,您将看到一条“欢迎”消息,否则将返回“错误”。
💻 您可以在此处查看此代码。
🥁useOptimistic()
钩子
useOptimistic
根据 React 文档,是一个 React Hook,可让您在异步操作正在进行时显示不同的状态。
这个钩子将有助于增强用户体验,并应该导致更快的响应。这对于需要与服务器交互的应用程序非常有用。
这是钩子的语法useOptimistic
:
const [ optimisticMessage, addOptimisticMessage] = useOptimistic(state, updatefn)
例如,当响应正在进行时,我们可以显示一个“状态”,以便为用户提供立即响应。一旦服务器返回实际响应,“乐观”状态将被它取代。
useOptimistic
假设请求成功,该挂钩将立即更新 UI。名称为“乐观”,因为用户将看到执行操作的乐观(成功)结果,即使该操作实际上需要时间才能完成。
让我们看看如何实现该useOptimistic
钩子。下面的代码显示了单击“提交”按钮 <form input> (Sending...)
直到没有响应为止的乐观状态。
import { useOptimistic, useState } from "react";
const Optimistic = () => {
const [messages, setMessages] = useState([
{ text: "Hey, I am initial!", sending: false, key: 1 },
]);
const [optimisticMessages, addOptimisticMessage] = useOptimistic(
messages,
(state, newMessage) => [
...state,
{
text: newMessage,
sending: true,
},
]
);
async function sendFormData(formData) {
const sentMessage = await fakeDelayAction(formData.get("message"));
setMessages((messages) => [...messages, { text: sentMessage }]);
}
async function fakeDelayAction(message) {
await new Promise((res) => setTimeout(res, 1000));
return message;
}
const submitData = async (userData) => {
addOptimisticMessage(userData.get("username"));
await sendFormData(userData);
};
return (
<>
{optimisticMessages.map((message, index) => (
<div key={index}>
{message.text}
{!!message.sending && <small> (Sending...)</small>}
</div>
))}
<form action={submitData}>
<h1>OptimisticState Hook</h1>
<div>
<label>Username</label>
<input type="text" name="username" />
</div>
<button type="submit">Submit</button>
</form>
</>
);
};
export default Optimistic;
fakeDelayAction
是一种延迟提交事件的假方法。这是为了表现乐观的状态。submitData
是行动。该方法负责表单提交。这也可能是异步的。sendFormData
负责将表格发送至fakeDelayAction
- 设置默认状态。
messages
将在 as 输入中使用useOptimistic()
并将在 中返回optimisticMessages
。
const [messages, setMessages] = useState([{ text: "Hey, I am initial!", sending: false, key: 1 },]);
现在,让我们了解更多细节:
在里面submitData
,我们正在使用addOptimisticMessage
.这将添加表单数据,以便它可以在optimisticMessage
.我们将使用它在 UI 中显示一条消息:
{optimisticMessages.map((message, index) => (
<div key={index}>
{message.text}
{!!message.sending && <small> (Sending...)</small>}
</div>
))}
💻 您可以在此处查看此代码。
以下是我们了解到的 3 个表单钩子的总结:
❓我现在可以使用 React 19 吗?
截至目前,上述所有功能都在金丝雀版本中可用。您可以在这里了解更多信息。正如 React 团队所建议的,目前不要将它们用于面向客户/用户的应用程序。 为了您自己的学习,或者只是为了好玩,请随意玩耍。
如果您想知道 React19 计划何时发布,可以关注Canary Releases获取更新。
要了解更多信息,您可以在以下位置关注 React 团队以获取最新信息:
🌟总结
我们在本文中介绍了很多内容。以下是 React v19 令人兴奋的变化的快速总结:
- 🤖 未来版本的 React 中将会引入一个新的 React 编译器。
- 🙌🏽 我们现在将拥有自动重新渲染、记忆以及状态和 UI 的优化。
- 🔮 将会有一些像
use()
这样的新钩子将有助于简化 Promise 和异步代码。 - ⚙️ React 中现在将提供服务器端组件支持。
useFormStatus()
📝 我们将使用操作 、 、useStatusForm()
和进行更好的表单处理useOptimistic()
。- 🖼 React 将通过在后台使用 Suspense 来优化资源加载以提高性能。
- 🔗 我们将在 React 中集成 Web 组件。