-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
44e402e
commit f81c7cd
Showing
5 changed files
with
788 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
--- | ||
title: React 19 有哪些变化 - 1 | ||
published_at: 2024-12-09T15:00:00.000Z | ||
snippet: React V19 change log 解读. | ||
--- | ||
|
||
React 19 就这么突然的发布了, 其实在去年的 React 开发者大会上就有预告, 这个版本会带来一些重大的变化, 目前我们公司的技术栈已经从 Vue 迁移到了 React, 了解新的 React 变化对我来说还是挺重要的, 接下来几天我阅读 React 19 的官方博客, 把变化记录下来, 也方便大家了解. | ||
|
||
## React 19 新特性总结 | ||
|
||
React 19 带来了很多新特性, 官方文档第一部分就是新特性的总结: | ||
|
||
## 新功能:Actions | ||
|
||
在 React 应用中,常见的需求是执行数据变更并更新状态,例如用户提交表单后修改名称。在 React 19 中,引入了 **Actions** 来自动管理这些操作,从而简化开发流程: | ||
|
||
- **异步过渡**:支持使用 `useTransition` 自动管理 `isPending` 状态。 | ||
- **挂起状态**:Actions 提供了请求开始到结束的挂起状态。 | ||
- **乐观更新**:通过新钩子 `useOptimistic` 支持即时反馈。 | ||
- **错误处理**:Actions 提供内置的错误处理机制。 | ||
- **表单支持**:表单的 `action` 和 `formAction` 属性可以直接传递函数,自动提交并重置表单。 | ||
|
||
使用示例: | ||
|
||
```javascript | ||
function ChangeName({ name, setName }) { | ||
const [error, submitAction, isPending] = useActionState( | ||
async (previousState, formData) => { | ||
const error = await updateName(formData.get("name")); | ||
if (error) return error; | ||
redirect("/path"); | ||
return null; | ||
}, | ||
null | ||
); | ||
|
||
return ( | ||
<form action={submitAction}> | ||
<input name="name" defaultValue={name} /> | ||
<button disabled={isPending}>Update</button> | ||
{error && <p>{error}</p>} | ||
</form> | ||
); | ||
} | ||
``` | ||
|
||
--- | ||
|
||
## 新钩子:`useActionState` | ||
|
||
`useActionState` 用于简化 Actions 的常见用例: | ||
|
||
- 接受一个异步函数并返回错误状态、提交函数和挂起状态。 | ||
- 适用于处理乐观更新和表单提交。 | ||
|
||
--- | ||
|
||
## 新钩子:`useOptimistic` | ||
|
||
`useOptimistic` 支持在请求进行时显示乐观状态,操作完成后自动回退到真实状态。例如: | ||
|
||
```javascript | ||
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}> | ||
<input name="name" defaultValue={optimisticName} /> | ||
<button>Change Name</button> | ||
</form> | ||
); | ||
} | ||
``` | ||
|
||
--- | ||
|
||
## 新 API:`use` | ||
|
||
React 19 提供了 `use` API,用于在渲染期间读取资源(例如 Promise 或 Context),支持挂起并自动切换状态: | ||
|
||
```javascript | ||
function Comments({ commentsPromise }) { | ||
const comments = use(commentsPromise); // 自动挂起直到数据加载完成 | ||
return comments.map((comment) => <p>{comment}</p>); | ||
} | ||
``` | ||
|
||
注意事项: | ||
|
||
- 不支持在渲染过程中创建的 Promise。 | ||
- 支持条件调用,未来可能扩展更多资源类型。 | ||
|
||
--- | ||
|
||
## React DOM 静态 API | ||
|
||
新增两个静态站点生成 API: | ||
|
||
- `prerender` | ||
- `prerenderToNodeStream` | ||
|
||
这些 API 支持等待数据加载并生成静态 HTML,适用于 Node.js 和 Web 流环境。 | ||
|
||
示例: | ||
|
||
```javascript | ||
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" } }); | ||
} | ||
``` | ||
|
||
--- | ||
|
||
## React Server Components | ||
|
||
**服务器组件**允许在客户端应用或 SSR 服务器之外的环境中提前渲染组件: | ||
|
||
- 稳定版本可用,但底层 API 尚未完全固定。 | ||
- 支持全栈 React 架构。 | ||
|
||
--- | ||
|
||
## Server Actions | ||
|
||
**服务器操作**支持从客户端组件调用在服务器上执行的异步函数: | ||
|
||
- 通过 `"use server"` 指令创建服务器操作。 | ||
- 服务器组件不需要特殊指令。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
--- | ||
title: React 19 有哪些变化 - 2 | ||
published_at: 2024-12-10T15:00:00.000Z | ||
snippet: React V19 change log 解读. | ||
--- | ||
|
||
这篇文章在第二部分介绍了一些对之前特性的升级. | ||
|
||
# React 19 新特性更新 | ||
|
||
## ref 作为 props 使用 | ||
|
||
在 React 19 中,函数组件可以直接将 `ref` 作为 `props` 访问,无需使用 `forwardRef`: | ||
|
||
```javascript | ||
function MyInput({ placeholder, ref }) { | ||
return <input placeholder={placeholder} ref={ref} />; | ||
} | ||
|
||
// 使用方式 | ||
<MyInput ref={ref} />; | ||
``` | ||
|
||
### 改进点: | ||
|
||
- 新的函数组件无需再使用 `forwardRef`。 | ||
- React 将发布一个代码迁移工具(codemod)来自动更新现有代码。 | ||
- 在未来版本中,`forwardRef` 将会被废弃。 | ||
|
||
**注意**: | ||
传递给类组件的 `ref` 不会作为 `props` 传递,因为它们引用的是组件实例。 | ||
|
||
--- | ||
|
||
## 改进的 Hydration 错误报告 | ||
|
||
React 19 改进了在 `react-dom` 中的 hydration 错误报告。 | ||
|
||
### 旧错误日志: | ||
|
||
在开发模式下,错误信息通常分散且缺乏具体上下文: | ||
|
||
```console | ||
Warning: Text content did not match. Server: “Server” Client: “Client” | ||
... | ||
``` | ||
|
||
### 新错误日志: | ||
|
||
现在,React 会输出一条包含详细差异的错误信息: | ||
|
||
```console | ||
Uncaught Error: Hydration failed because the server rendered HTML didn’t match the client... | ||
<App> | ||
<span> | ||
+ Client | ||
- Server | ||
``` | ||
|
||
### 可能的原因: | ||
|
||
- 使用了客户端/服务器分支代码(如 `typeof window !== 'undefined'`)。 | ||
- 变量输入(如 `Date.now()` 或 `Math.random()`)。 | ||
- 本地化的日期格式化不一致。 | ||
- 没有同步 HTML 数据快照。 | ||
- 无效的 HTML 标签嵌套。 | ||
- 浏览器扩展导致的 HTML 修改。 | ||
|
||
更多信息请参阅 [hydration-mismatch 文档](https://react.dev/link/hydration-mismatch)。 | ||
|
||
--- | ||
|
||
## <Context> 作为 Provider 使用 | ||
|
||
在 React 19 中,可以直接使用 `<Context>` 渲染 Context 提供者,而不再需要 `<Context.Provider>`: | ||
|
||
```javascript | ||
const ThemeContext = createContext(""); | ||
|
||
function App({ children }) { | ||
return <ThemeContext value="dark">{children}</ThemeContext>; | ||
} | ||
``` | ||
|
||
### 改进点: | ||
|
||
- `<Context>` 可以直接作为提供者。 | ||
- 将发布迁移工具以转换现有 `<Context.Provider>` 实现。 | ||
- 在未来版本中,`<Context.Provider>` 将被废弃。 | ||
|
||
--- | ||
|
||
## refs 的清理函数 | ||
|
||
React 19 支持在 `ref` 回调中返回清理函数,用于在元素从 DOM 中移除时重置 `ref`: | ||
|
||
```javascript | ||
<input | ||
ref={(ref) => { | ||
// 创建 ref | ||
return () => { | ||
// 清理 ref | ||
}; | ||
}} | ||
/> | ||
``` | ||
|
||
### 改进点: | ||
|
||
- 清理函数适用于 DOM refs、类组件 refs 以及 `useImperativeHandle`。 | ||
- React 不再在卸载组件时调用带 `null` 的 ref 函数。 | ||
|
||
**注意**:由于清理函数的引入,TypeScript 现在会拒绝从 ref 回调中返回非清理函数的值。 | ||
|
||
修复示例: | ||
|
||
```diff | ||
- <div ref={(current) => (instance = current)} /> | ||
+ <div ref={(current) => { instance = current; }} /> | ||
``` | ||
|
||
可使用 `no-implicit-ref-callback-return` 的迁移工具修复该模式。 | ||
|
||
--- | ||
|
||
## `useDeferredValue` 初始值 | ||
|
||
React 19 为 `useDeferredValue` 添加了 `initialValue` 选项: | ||
|
||
```javascript | ||
function Search({ deferredValue }) { | ||
const value = useDeferredValue(deferredValue, ""); // 初始值为 '' | ||
return <Results query={value} />; | ||
} | ||
``` | ||
|
||
### 特性: | ||
|
||
- 初次渲染时返回 `initialValue`,然后在后台重新渲染并使用 `deferredValue`。 | ||
|
||
更多信息请参阅 [useDeferredValue 文档](https://react.dev/link/useDeferredValue)。 |
Oops, something went wrong.