当前位置: 首页 > news >正文

React 19 新特性集合

前言:https://juejin.cn/post/7337207433868197915

新 React 版本信息

伴随 React v19 Beta 的发布,React v18.3 也一并发布。

React v18.3相比最后一个 React v18 的版本 v18.2 ,v18.3 添加了一些警告提示,便于尽早发现问题,从而在升级 React v19 时更容易。

React 18.3 更新内容

React 18.3 相对于 18.2 增加了对废弃 API 的警告以及其他为 React 19 所需的更改。

  1. React
  • 允许向 this.refs 写入以支持字符串 ref 的代码模式转换。
  • 在 StrictMode 外部使用已废弃的 findDOMNode 时,将发出警告。
  • 对使用已废弃的测试工具方法时发出警告。
  • 在 StrictMode 外部使用已废弃的遗留 Context 时,将发出警告。
  • 在 StrictMode 外部使用已废弃的字符串 ref 时,将发出警告。
  • 对函数组件中使用已废弃的 defaultProps 发出警告。
  • 当在组件或元素中展开 key 时,将发出警告。
  • 从测试工具中使用 act 时,如果方式不当,将发出警告。
  1. React DOM
  2. 对使用已废弃的 unmountComponentAtNode 方法时发出警告。
  3. 对使用已废弃的 renderToStaticNodeStream 方法时发出警告。

React v18 发布后,带来了以并发特性为主的各种新 API ( startTransition / useDeferredValue 等 )、新运作模式、及 stream SSR 上的改进等,其相比 React v17 像是一个增量的升级版。

而 React v19 则不然,包含了 大量 细小的、或破坏性的变更(如document meta data 和asset loading)。

由于 React v18 canary 已迭代很久,本次更新中的很多内容属于历史已公布的内容,故不会重复做展开介绍。

React v19 中的新特性 – 概述
以下是 React 19 将具有的新特性的快速概述:

🤖 React 编译器react compiler:React 正在努力实现一个新的编译器。目前,Instagram 已经在利用这项技术,它将在未来版本的 React 中发布。

🔥 服务器组件react server component:经过多年的开发,React 引入了服务器组件的概念。您现在可以在 Next.js 中使用此功能。

💪 动作action:动作还将彻底改变我们与 DOM 元素的交互方式。

🌇 文档元数据document metadata:另一个急需改进的方面即将到来,使开发人员能够用更少的代码实现更多功能。

💼 资源加载asset loading:这将使资源能够在后台加载,从而改善应用程序的加载时间和用户体验。

⚙️ Web 组件:这特别令人着迷:React 代码现在将使我们能够集成 Web 组件。我对此发展非常激动,因为它将开启无数可能性。

🪝 增强型钩子:令人兴奋的新钩子即将问世,将彻底改变我们的编码体验。

  • 新的 use() 钩子
  • useFormStatus() 钩子
  • useFormState() 钩子
  • useOptimistic() 钩子

React 19 将解决 React 长期存在的挑战之一:过度重新渲染的问题。开发人员历来花费了大量时间来解决这个问题,这经常导致性能问题。

对导致重新渲染的代码进行持续追踪和优化工作一直是工程师们的重复任务。但是有了 React 19,这个问题将得到缓解。框架将自动处理重新渲染,简化开发流程。

以前,开发人员依赖 useMemo()、useCallback()、memo 等技术来管理重新渲染。但是在 React 19 中,这样的手动干预将不再必要。

框架将在幕后智能识别和记忆代码,从而产生更清晰和更有效的代码。 

React v20
目前已知内容:

  • React compiler (编译优化器,如 React forget )不等于 React v19 。
  • Activity ( 原 Offscreen )可能在 React v20 推出。

V19新特性介绍

1. React 编译器

这是为了性能做的更新。优化重新渲染的一种方式是手动使用 useMemo()、useCallback() 和 memo API。根据 React 团队的说法,这是一种“合理的手动妥协”。他们的愿景是让 React 管理这些重新渲染。但是 React 团队意识到手动优化很繁琐,而社区的反馈鼓励他们解决这个问题。因此,React 团队创建了“React 编译器”。React 编译器现在将管理这些重新渲染。React 将自动决定何时以及如何更改状态并更新 UI。

React Compiler,在开发者不调整任何代码的情况下,自动优化项目性能。帮助我们在不使用 memo/useMemo/useCallback 的情况下,方便的处理好项目 re-render 的问题。你的项目最终只会在需要更新的地方 re-render。React Compiler 编译之后,你的代码并不会改变现有渲染机制,而是在已有机制下完成对项目的优化。

React Compiler能够将React代码编译成更为优化的JavaScript代码。这一改变能够显著提升React应用的运行效率。编译器的引入不仅优化了代码的执行时间,还减少了浏览器的负载,从而使应用响应更快,交互更流畅。

与依赖追踪的细粒度更新不同,React Compiler 通过记忆的方式,让组件更新只发生在需要更新的组件,从而减少大量 re-render 的组件。

但是请注意,React Compiler 并非全能,如果你写的代码过于灵活,无法被提前预判执行行为,那么 React Compiler 将会跳过这一部分的优化。因此好的方式是在项目中引入严格模式,在严格模式的指导下完成的开发,基本都在 React Compiler 的辐射范围之内

例子1:在 React19 之后,不再需要使用 useMemo() 钩子,因为 React 编译器将自行进行记忆。

之前:

import React, { useState, useMemo } from 'react';function ExampleComponent() {const [inputValue, setInputValue] = useState('');// 缓存检查输入值是否为空的结果const isInputEmpty = useMemo(() => {console.log('检查输入是否为空...');return inputValue.trim() === '';}, [inputValue]);return (<div><inputtype="text"value={inputValue}onChange={(e) => setInputValue(e.target.value)}placeholder="输入一些内容..."/><p>{isInputEmpty ? '输入为空' : '输入不为空'}</p></div>);
}export default ExampleComponent;
之后:不需要再使用 useMemo 缓存值了 - React19 将在底层自行处理。
import React, { useState } from 'react';function ExampleComponent() {const [inputValue, setInputValue] = useState('');const isInputEmpty = () => {console.log('检查输入是否为空...');return inputValue.trim() === '';});return (<div><inputtype="text"value={inputValue}onChange={(e) => setInputValue(e.target.value)}placeholder="输入一些内容..."/><p>{isInputEmpty ? '输入为空' : '输入不为空'}</p></div>);
}export default ExampleComponent;

2. 服务器组件 

React Server Components 是 React 在探索前端边界的又一次突破性的创举。它是一种新概念组件。我们可以在构建时运行一次组件,以提高页面的渲染速度。

预渲染、增量渲染、流式传输等概念对提高大型复杂项目的用户体验有非常大的帮助。好消息是,RSC 已经在 Next.js 中得到落地实践。

React 19加强了对服务端组件(Server Components)的支持,这些组件在服务器上渲染完成后再发送到客户端,极大地提高了页面加载速度。

这一特性尤其适合内容重的网站应用,允许部分组件的逻辑在服务器上执行,而不会发送相关的JavaScript到客户端。这样做的好处包括减少了传输数据量,加快了首次加载速度,并优化了SEO。

举个例子:

// ServerUserInfo.react.server.js
// 注意:这个文件的扩展名为 .server.js,表示它是一个服务端组件。import { db } from './database';// 从数据库中获取用户信息的函数
async function fetchUserData(userId) {return db.query('SELECT * FROM users WHERE id = $1', [userId]);
}function ServerUserInfo({ userId }) {const userData = fetchUserData(userId);return (<div><h1>User Information</h1><p>Name: {userData.name}</p><p>Email: {userData.email}</p></div>);
}export default ServerUserInfo;

这样我们就创建了一个服务端组件,它直接从数据库获取用户信息,并在服务器上进行渲染。这样做还可以保护用户的敏感信息,因为这些数据不会被发送到客户端,同时增强了安全性,并且由于减少了客户端处理逻辑,页面加载速度更快。

在客户端中,我们只需要引用这个组件,并在构建时配置好相关的服务端渲染逻辑。

服务端组件带来的额优势:

  • SEO:服务器渲染的组件通过向网络爬虫提供更可访问的内容来增强搜索引擎优化。
  • 性能提升:服务器组件有助于更快地加载页面和改善整体性能,特别是对于内容密集型应用程序。
  • 服务器端执行:服务器组件使在服务器上执行代码变得无缝和高效,使诸如 API 调用之类的任务变得轻松。

目前 Next.js 支持服务器端组件。React 中所有组件默认都是客户端的。只有当你使用 ‘use server’ 时,组件才是服务器组件
可以在同一项目中的任何 React 组件中导入 requestUsername。在导入服务器组件后,我们可以使用“Actions”(我们很快会学习到)执行特定任务。

'use server';export default async function requestUsername(formData) {const username = formData.get('username');if (canRequest(username)) {// ...return 'successful';}return 'failed';
}

3. 动作 action

submitData 是服务器组件中的动作。form 是一个客户端组件,它使用 submitData 作为动作。submitData 将在服务器上执行。客户端(form)和服务器(submitData)组件之间的通信只有通过动作属性才能实现。

"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;

相关新增的api:

新 API :useActionState
重要性:★

参考信息:useActionState 代码例子

此 API 原名为 useFormState ,主要用于联动原生 <form /> 表单提交,现代开发更多使用高级表单库,故此特性不重要。

新 API :useFormStatus
重要性:★

参考信息:useFormStatus 文档

此 API 与 useFormState 联动使用,现代开发更多使用高级表单库,故此特性不重要。

新 API :useOptimistic
重要性:★★

参考信息:useOptimistic 文档

通过此 API 派生其他的 state ,从而在提交动作时,立即乐观更新此值来优化用户视觉上的交互体验。

要实现乐观更新,必然要编写许多额外逻辑,同时现代请求库(如 react-query 、SWR 等)早已提供了乐观更新的功能。然而更多时候,我们没有精力和工时来提升用户体验,过度提升体验反而会造成更多冗余的乐观更新逻辑导致后续维护困难,展示 loading 已经足够,故此 API 不重要,若不是有心为之,则很难用到。

4. Web 组件

Web 组件允许你使用原生 HTML、CSS 和 JavaScript 创建自定义组件,并将它们无缝地整合到你的 Web 应用程序中,就像它们是标准 HTML 标签一样。

之前,在 React 中集成 Web 组件并不简单。通常情况下,要么需要将 Web 组件转换为 React 组件,要么安装额外的包并编写额外的代码,以使 Web 组件与 React 协同工作。

React 19改进了对Web组件的支持,使得在React项目中整合使用Web标准组件变得更加无缝。这使得开发者可以利用广泛的Web组件生态系统,而不必为了在React中使用它们而写大量的封装代码。

import React from 'react';function CustomButtonComponent() {return (<><my-button>Click Me!</my-button></>);
}export default CustomButtonComponent;

在这个示例中,<my-button>是一个自定义的Web组件,它可以直接在React中使用,无需任何特别的封装或桥接代码。这种整合提高了代码的复用性,并允许React开发者利用现有的Web组件库。

可能有的同学会说,这一个自定义的标签有什么用呢?回答是:非常有用。

因为在React 19的现代Web框架中使用Web组件时,<my-button>并不是一个普通的HTML标签。

它实际上是一个Web组件——这是一种使用自定义元素、Shadow DOM、HTML模板封装好的可重用组件。 当你在Web应用中使用像<my-button>这样的自定义元素时,浏览器会渲染出这个元素的定义所包含的所有样式和行为。

这些自定义元素的行为和外观完全由你定义的Web组件的JavaScript和CSS控制。以下假设定义了一个自定义的web组件:

class MyButton extends HTMLElement {constructor() {super(); // 调用父类的constructorconst shadowRoot = this.attachShadow({mode: 'open'});shadowRoot.innerHTML = `<style>button {background-color: blue;color: white;padding: 10px 20px;border: none;border-radius: 5px;cursor: pointer;}</style><button><slot></slot></button>`;}
}// 定义新的自定义元素
customElements.define('my-button', MyButton);

5. 文档元数据 

对元数据的管理变得更加简单。React 19引入了可以直接在React组件中使用HTML元数据标签的能力,这样开发者就不再需要依赖如react-helmet这样的库来动态更新文档头部信息。

1)基本元数据标签

考虑到 SSR 的完备性,使用第三方库插入元信息仍然更好,所以此特性不重要。

之前:

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;

 现在:在 React 中以前是不可能的。唯一的方法是使用像 react-helmet 这样的包。

function HomePage() {return (<><title>主页 - 我的网站</title><meta name="description" content="这是我的网站主页,提供各种服务信息。" /><h1>欢迎来到我的网站</h1><p>这里有丰富的资源和信息。</p></>);
}

在这个示例中,<title><meta>标签直接放置在组件返回的JSX中。

React 19可以处理这些标签,并将它们正确地渲染到HTML文档的头部。这种方式简化了元数据的管理,特别是在单页面应用中,可以更灵活地针对不同页面设置SEO相关的元数据。

2)样式表支持

参考信息:插入 link / meta / script / style / title 文档说明

对于使用 webpack 等打包工具进行模块化开发的现代,除 特别的样式覆盖 或 异步分包、构建工具缺陷 等原因导致对顺序出现 workaround 的需求外,一般我们在业务项目内不会接触到手动管理标签的情况,故此特性不重要

在Web开发中,样式表的管理至关重要,无论是通过外部链接(<link rel="stylesheet" href="...">)还是内嵌方式(<style>...</style>)引入,都需要在 DOM 中精准布局,以确保样式优先级得到妥善处理。然而,构建一个能够支持组件内部样式表组合的机制往往十分繁琐,因此开发者常常面临权衡:要么将样式远离其依赖的组件加载,牺牲组织性;要么依赖外部样式库,增加额外的复杂性。

React 19 针对这一挑战提供了内置支持,不仅简化了样式表的管理流程,还进一步增强了与客户端并发渲染和服务器端流式渲染的集成能力。通过指定样式表的优先级,React 将自动处理样式表在DOM中的插入顺序,确保在展示依赖于特定样式规则的内容之前,相关的样式表(无论外部还是内嵌)已经被加载并应用。

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>)
}

在服务端渲染过程中,React会将样式表包含在<head>标签中,以确保浏览器在加载完成前不会进行页面绘制。如果在已经开始流式传输后才发现样式表,React 将确保在客户端将样式表插入到<head>标签中,然后再展示依赖于该样式表的Suspense边界的内容。

在客户端渲染过程中,React会等待新渲染的样式表加载完成后再提交渲染结果。如果在应用中的多个位置渲染了这个组件,React将确保样式表在文档中只被包含一次。

function App() {return <><ComponentOne />...<ComponentOne /> // 不会导致 DOM 中出现重复的样式表链接</>
}

对于那些习惯于手动加载样式表的开发者来说,React 19 的这一改进为他们提供了一个便利的机会。现在,可以将样式表直接放在依赖它们的组件旁边,这不仅有助于提升代码的可读性和可维护性,使得开发者可以更加清晰地了解每个组件的样式依赖关系,而且还能够确保只加载真正需要的样式表。

此外,样式库和与打包器集成的样式工具也可以采用这一新特性。即使开发者不直接渲染自己的样式表,只要他们所使用的工具升级到支持这一功能,他们同样能够享受到这一改进带来的好处。

 3)异步脚本支持

在HTML中,普通脚本(<script src="...">)和延迟脚本(<script defer src="...">)按照文档顺序加载,这限制了它们在组件树深处的灵活使用。然而,异步脚本能够以任意顺序加载,为开发者提供了更大的灵活性。

React 19 针对异步脚本提供了增强的支持,允许开发者在组件树的任何位置渲染它们,直接放在实际依赖该脚本的组件内部。这大大简化了脚本的管理,无需再担心脚本实例的重新定位和去重问题。

现在,你可以在组件中这样使用异步脚本:

function MyComponent() {  return (  <div>  <script async src="..." />  Hello World  </div>  );  
}  function App() {  return (  <html>  <body>  <MyComponent />  ...  <MyComponent /> // 不会导致DOM中出现重复的脚本  </body>  </html>  );  
}

在所有渲染环境中,异步脚本都将进行去重处理,因此即使多个不同的组件渲染了同一个脚本,React 也只会加载和执行该脚本一次。

在服务端渲染中,异步脚本将被包含在<head>标签中,并优先于阻止绘制的更关键资源(如样式表、字体和图像预加载)之后加载。

6. 资源加载 

通常情况下,浏览器首先渲染视图,然后是样式表、字体和图像。这可能导致从未样式化(或未样式化内容的闪烁)到样式化视图的闪烁。

为了解决这个问题,开发人员通常会添加自定义代码来检测这些资源何时准备就绪,确保仅在一切加载完毕后显示视图。

在 React 19 中,图像和其他文件将在用户浏览当前页面时在后台加载。这个改进应该有助于改善页面加载时间并减少等待时间。

此外,React 还引入了用于资源加载的生命周期 Suspense,包括脚本、样式表和字体。这个特性使 React 能够确定内容何时准备好显示,消除了任何“未样式化”闪烁。

还有新的资源加载 API,如 preload 和 preinit,可以提供更大的控制权,使资源何时加载和初始化。

通过允许资源在后台异步加载,React 19 将最小化等待时间,并确保用户可以在没有中断的情况下与内容交互。这种优化不仅提升了 React 应用程序的性能,也为用户提供了更愉快的浏览体验。

7. 新的 React Hooks

React19 想要彻底改变我们在项目开发中的 UI 交互方式。因此对于 React19 而言,Suspense、ErrorBoundary、Action 的重要性将会变得越来越高。

React 19 之前,React 高手与普通开发者之间,开发的项目无论是从性能上、还是从代码优雅上差距都非常大。因此不同的人对于 React 的感受完全不一样。

而 React 19 则借由推出一些新的 hook,暗中传递一种框架思维「最佳实践」,这将会极大的拉进普通开发者与顶尖高手之间的差距。对于大多数 React 开发者而言,这会是一个极大的提升。

这一意图在 React 新的官方文档与 Next.js 中提现得非常明显

React 19在钩子函数方面也进行了增强,新增了use钩子。因此使用 useMemo、forwardRef、useEffect 和 useContext 的方式将发生变化。

这个钩子让我们在处理异步操作和资源获取更为便捷。通过use钩子,开发者可以在组件中直接挂载资源,如通过promise获取数据,React将暂停该组件的渲染直到数据加载完成,从而简化了代码结构并减少了不必要的渲染。

React19 的 大部分更新,几乎都是围绕如何在开发中尽量不用或者少用 useEffect 来展开。在之前的项目开发中,useEffect 是我们处理异步问题必须使用的重要 hook 之一,他几乎存在于每一个页面组件之中。

React 19 则引入了新的 hook,让我们处理异步开发时,不再需要 useEffect,从而极大的改变我们的开发方式。

使用 use 钩子处理异步数据
在React 19中,use 钩子可以让我们更简洁地处理异步数据。下面是一个使用use钩子来请求并展示用户数据的示例:

import { use } from 'react';  // 引入use钩子function UserProfile({ userId }) {const userPromise = fetch(`https://api.example.com/users/${userId}`).then(response => response.json());// 使用use钩子处理异步请求const user = use(userPromise);return (<div><h1>{user.name}</h1><p>Email: {user.email}</p><p>Location: {user.location}</p></div>);
}export default UserProfile;

use钩子允许组件在渲染过程中直接使用由 promise 返回的数据。当数据加载完成时,组件将重新渲染以显示数据。

对比旧的异步处理方式,在React 19之前,处理异步数据通常需要使用useState和useEffect钩子,如下例子所示:

import React, { useState, useEffect } from 'react';function UserProfile({ userId }) {const [user, setUser] = useState(null);useEffect(() => {fetch(`https://api.example.com/users/${userId}`).then(response => response.json()).then(data => setUser(data));}, [userId]);  // 依赖项数组中的userId确保当userId变化时重新发起请求if (!user) return <div>Loading...</div>;return (<div><h1>{user.name}</h1><p>Email: {user.email}</p><p>Location: {user.location}</p></div>);
}export default UserProfile;

在这种传统方法中,我们需要管理一个状态变量user来存储用户数据,并使用useEffect来处理异步请求和响应。这不仅增加了代码量,也增加了组件的复杂度。

例子2:

在项目开发中,新页面渲染时请求一个接口的场景非常常见。新的架构思维的开发代码如下所示。

首先我们需要定义一个 API 用于请求数据。

const api = async () => {const res = await fetch('https://api.chucknorris.io/jokes/random')return res.json()
}

然后创建一个函数组件,并执行该 api

export default function Index() {const __api = api()return (<div><div id='tips'>初始化时,自动获取一条数据内容</div><Suspense fallback={<div>loading...</div>}><Item api={__api} /></Suspense></div>)
}

最后在子组件中,获取 api 执行之后得到的数据

const Item = (props) => {const joke = use(props.api)return (<div><div>{joke.value}</div></div>)
}

大家可以自行感受一下新的开发方式与以前基于 useEffect 请求数据有什么不同之处。

例子3:不再使用 useContext(),而是使用 use(context)。

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 (<divclassName={`p-4 rounded-md ${theme === 'light' ? 'bg-white' : 'bg-gray-800'}`}><h1className={`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><buttononClick={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

 

8. 功能改进

1)ref 作为属性

ref 现在将作为 props 传递,而不是使用 forwardRef() 钩子。这将简化代码。因此,在 React19 之后,你将不再需要使用 forwardRef()。

之前:这是在 React 19 之前使用 forwardRef() 的示例:
import React, { forwardRef } from 'react';const ExampleButton = forwardRef((props, ref) => (<button ref={ref}>{props.children}</button>
));
之后:ref 可以作为 props 传递。不再需要 forwardRef()。
import React from 'react';const ExampleButton = ({ ref, children }) => (<button ref={ref}>{children}</button>
);//...  <ExampleButton ref={ref} />

2)作为提供者

React 19 允许直接将 <Context> 用作提供者,而无需使用传统的 <Context.Provider> 写法:

const ThemeContext = createContext('');  function App({children}) {  return (  <ThemeContext value="dark">  {children}  </ThemeContext>  );  
}

这种新的语法更加简洁直观。为了方便开发者升级现有代码,React 团队将发布一个代码转换工具,能够自动将现有的 <Context.Provider> 转换为新的 <Context> 提供者。未来版本中,将逐步弃用 <Context.Provider>,以推动 React 社区向更加简化的语法过渡。

3)refs 清理函数

现在支持从 ref 回调函数中返回一个清理函数:

<input  ref={(ref) => {  // 创建 ref  // 新增:返回一个清理函数,当元素从 DOM 中移除时重置 ref。  return () => {  // ref 的清理工作  };  }}  
/>

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

由于引入了 ref 清理函数的机制,现在 TypeScript 将拒绝从 ref 回调函数中返回除清理函数以外的任何内容。为了避免这个问题,我们通常建议避免使用隐式返回,比如将赋值操作放在花括号中,如下所示:

  • 原来的写法:
<div ref={current => (instance = current)} />
  • 优化后的写法:
<div ref={current => { instance = current; }} />

这种改变是因为 TypeScript 无法判断原始代码中返回的是否应该是清理函数,还是无意中的隐式返回值。通过将赋值操作明确地包裹在花括号中,确保了 ref 回调中不会意外地返回任何值,除非有意为之。

为了自动化这种模式的转换,可以使用 no-implicit-ref-callback-return 规则进行代码转换。这将帮助你在升级 React 版本时更顺畅地处理 ref 相关的代码。

4)useDeferredValue 的初始值

React 19 为 useDeferredValue 引入了 initialValue 选项,该选项允许指定组件首次渲染时返回的值。

function Search({ deferredValue }) {  // 在组件首次渲染时,返回 initialValue 作为 value。  // 随后,useDeferredValue 会在后台计划一次重渲染,使用 deferredValue 作为新的 value。  const value = useDeferredValue(deferredValue, { initialValue: '' });  return (  <Results query={value} />  );  
}

使用 initialValue 可以确保组件在首次渲染时能够立即显示一个占位值,而无需等待 deferredValue 的异步计算完成。随后,当 deferredValue 准备好时,useDeferredValue 会触发组件的后台重渲染,以显示最新的值。这有助于提升应用的响应性和用户体验。

5)资源预加载支持

新 API :preXXX 预加载资源

重要性:★★

参考信息:preconnect / prefetchDNS / preinit / preinitModule / preload / preloadModule 文档说明

在文档初始加载和客户端更新时,及时告知浏览器可能即将需要加载的资源,对于提升页面性能至关重要。React 19 引入了一系列新的API,旨在简化浏览器资源的加载和预加载过程,让开发者能够构建出流畅且高效的用户体验。

import { prefetchDNS, preconnect, preload, preinit } from 'react-dom';  function MyComponent() {  preinit('https://.../path/to/some/script.js', { as: 'script' }); // 提前加载并执行脚本  preload('https://.../path/to/font.woff', { as: 'font' }); // 预加载字体  preload('https://.../path/to/stylesheet.css', { as: 'style' }); // 预加载样式表  prefetchDNS('https://...'); // 当可能会从该主机请求资源但尚不确定时  preconnect('https://...'); // 当确定会从该主机请求资源但不确定具体资源时  
}

这些 API 调用会在渲染组件时生成相应的DOM标签,如下所示:

<html>  <head>  <!-- 链接根据其对页面加载的贡献程度进行优先级排序 -->  <link rel="prefetch-dns" href="https://..."> <!-- DNS预获取 -->  <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>

通过利用这些API,开发者可以优化页面的初始加载速度,减少用户等待时间。同时,在客户端更新时,预取和预加载资源也能帮助加快导航速度,提升用户体验。无论是通过预加载字体和样式表来减少页面渲染阻塞,还是通过预取DNS和预连接来加速资源请求,这些API都为开发者提供了强大的工具,使资源加载更加智能和高效。

分类来看:

  • preconnect 、prefetchDNS 等 API 将插入 <link rel="preconnect" /> 标签的行为命令化,但由于预加载时机越早越好,等到 React 应用运行后,已经错过了 preconnect 的最好时机,所以编写至 HTML 内或 SSR 仍然是首选方案,此类 API 不重要。
  • preinit / preload 等 API 将 脚本、样式 的加载命令化,但现代项目开发时已经内部模块化,使用 await import() 等懒加载行为已足够,故除了需要加载外部 脚本、样式 外,此 API 也不重要。

6)与第三方脚本和扩展的兼容性

在React 19中,对挂载过程进行了优化,以更好地兼容第三方脚本和浏览器扩展。

在客户端挂载时,如果渲染的元素与服务器返回的HTML中的元素不一致,React会触发客户端的重新渲染,以确保内容的正确性。然而,过去,若第三方脚本或浏览器扩展插入了某些元素,这会导致不匹配错误并触发不必要的客户端渲染。

现在,React 19 能够智能地跳过<head>和<body>中的意外标签,从而避免了因这些元素引发的不匹配错误。即使因为其他原因需要进行整个文档的重新渲染,React也会保留由第三方脚本和浏览器扩展插入的样式表,确保页面的完整性和一致性。

7)水合错误报告

React 19 在 react-dom 中对水合错误的报告进行了优化。过去,在开发模式下遇到水合不匹配时,系统往往只记录多个错误,而缺乏关于不匹配内容的具体信息。现在,引入了 diff 功能,使得客户端渲染与服务端渲染内容之间的差异一目了然。这一改进不仅提升了错误报告的清晰度,更有助于开发者迅速定位并修复水合相关问题,从而大幅提升开发效率。

现在只会记录一条包含不匹配内容差异的消息:

8)更好的错误报告

为了提供更细粒度的错误处理控制,还新增了两个根选项来与onRecoverableError相辅相成:

  • onCaughtError:当React在错误边界中成功捕获到错误时,此选项将被调用。
  • onUncaughtError:当错误被抛出且未能被任何错误边界捕获时,此选项将被触发。
  • onRecoverableError:当错误发生但React能够自动恢复时,该选项将起作用。

参考信息:onCaughtError / onUncaughtError / onRecoverableError 文档说明

这些新增选项不仅增强了React的错误处理能力,还赋予了开发者在不同错误场景下执行特定逻辑的能力。无论是进行错误日志的记录、发送错误报告,还是执行其他自定义操作,这些选项都能满足开发者的需求,帮助他们更有效地管理和应对React应用中的错误情况。

给 React 在全局 ReactDOM.createRoot 挂载时开放了一个全局捕获错误的出口:

ReactDOM.createRoot(document.getElementById('root')!, {onCaughtError: (error, errorInfo) => {// ...},
})

这可以避免在 ErrorBoundary 内部收集错误,而在全局更清真的统一处理(此处只是单纯报告错误,涉及到复杂的 ErrorBoundary 错误恢复和重试,仍然需要编写大量代码)。

注:不可以捕获 React 内的异步逻辑错误。

React 19 对错误处理进行了优化,旨在消除错误信息的重复,并为处理捕获和未捕获的错误提供了更多选项。例如,当渲染过程中发生错误并被错误边界捕获时,以前 React 会重复抛出相同的错误(一次是原始错误,另一次是在尝试自动恢复失败后),然后调用console.error输出错误发生位置的信息。

这种处理方式导致每个被捕获的错误都会被报告三次:

在 React 19 中将记录单个错误,并包含所有错误信息:


 

9)useRef 必须传入默认值
重要性:★★★

参考信息:useRef 入参更改说明

React v19 要求 useRef(defaultValue) 传入一个默认值,这会影响到所有历史 useRef() 未设定默认值的调用写法。

在以前,我们往往会通过 useRef<HTMLInputElement>(null!) 技巧 避免类型提示为空,因为此处 ref 必定存在,若存在默认值或采用技巧,则不存在此变动带来的问题,但相当一部分人并不会采用 React TypeScript 技巧 ,请多加留意。

10)React UMD 版本已被删除
重要性:★★★

参考信息:删除 UMD

仍有不少项目希望通过 external React UMD 的方式进行一些依赖外置化加载的设计,但未来 esm 是大势所趋,故 React v19 已删除 UMD 版本。

如还想通过外置形式使用 React ,需改为 esm 的 <script type="module"> 方式使用:

<script type="module">import React from "https://esm.sh/react@beta"import ReactDOM from "https://esm.sh/react-dom@beta/client"...
</script>

各种不重要的小变化

API 相关
  • ReactDOM.render / ReactDOM.hydrate 旧版渲染应用 API 已被删除( 链接 )

  • useDeferredValue 支持设定默认值( 链接 )
  • React.createFactory 已被删除( 链接 )
  • react-test-renderer/shallow 导出位置已被更改( 链接 )
  • unmountComponentAtNode 旧版卸载节点 API 已被删除( 链接 )
  • ReactDOM.findDOMNode API 已被删除( 链接 )
特性相关
  • 更好的 web components 支持( 链接 )

注:这是一个较瞩目的新特性,但大多数人很少使用 web component ,故只有特定用户群体才值得去关注。

体验相关
  • 水合出现差异时,报错信息更友好( 链接 )。
  • 优化了控制台错误打印的格式( 链接 )
  • useLayoutEffect 在服务端运行的警告已被删除( 链接 )
Class 组件相关
  • Class 组件的 propTypes / defaultProps 已被删除( 链接 )
  • Class 组件的 getChildContext 已被删除( 链接 )
  • Class 组件的字符串 ref="string" 已被删除( 链接 )
函数组件相关
  • 函数组件的 render() 渲染方式已被删除( 链接 )
测试相关
  • act 函数导出位置已转移至 react ( 链接 )
  • react-test-renderer 已弃用( 非删除, 链接 )

注:此包以前可能用于一些简单的组件测试,但现在已被弃用,请在所有 React 的测试中统一使用 RTL ( @testing-library/react ),这将是官方推荐的唯一测试库。

类型相关
  • ReactElement 类型被调整( 链接 )
  • 限定 React JSX 类型的命名空间( 链接 )
  • 注:为了避免各种 JSX 的类型在全局冲突,Vue v3.4 也限制了自己的命名空间。
  • useReducer 类型改进( 链接 )

新增api参考

相关文章:

React 19 新特性集合

前言&#xff1a;https://juejin.cn/post/7337207433868197915 新 React 版本信息 伴随 React v19 Beta 的发布&#xff0c;React v18.3 也一并发布。 React v18.3相比最后一个 React v18 的版本 v18.2 &#xff0c;v18.3 添加了一些警告提示&#xff0c;便于尽早发现问题&a…...

耐高温水位传感器有哪些

耐高温水位传感器在现代液位检测技术中扮演着重要角色&#xff0c;特别适用于需要高温环境下稳定工作的应用场合。这类传感器的设计和材质选择对其性能和可靠性至关重要。 一种典型的耐高温水位传感器是FS-IR2016D&#xff0c;它采用了PPSU作为主要材质。PPSU具有优良的耐高温…...

Symfony国际化与本地化:打造多语言应用的秘诀

标题&#xff1a;Symfony国际化与本地化&#xff1a;打造多语言应用的秘诀 摘要 Symfony是一个高度灵活的PHP框架&#xff0c;用于创建Web应用程序。它提供了强大的国际化&#xff08;i18n&#xff09;和本地化&#xff08;l10n&#xff09;功能&#xff0c;允许开发者轻松创…...

ApolloClient GraphQL 与 ReactNative

要在 React Native 应用程序中设置使用 GraphQL 的简单示例&#xff0c;您需要遵循以下步骤&#xff1a; 设置一个 React Native 项目。安装 GraphQL 必要的依赖项。创建一个基本的 GraphQL 服务器&#xff08;或使用公共 GraphQL 端点&#xff09;。从 React Native 应用中的…...

【贡献法】2262. 字符串的总引力

本文涉及知识点 贡献法 LeetCode2262. 字符串的总引力 字符串的 引力 定义为&#xff1a;字符串中 不同 字符的数量。 例如&#xff0c;“abbca” 的引力为 3 &#xff0c;因为其中有 3 个不同字符 ‘a’、‘b’ 和 ‘c’ 。 给你一个字符串 s &#xff0c;返回 其所有子字符…...

C#基于SkiaSharp实现印章管理(3)

本系列第一篇文章中创建的基本框架限定了印章形状为矩形&#xff0c;但常用的印章有方形、圆形等多种形状&#xff0c;本文调整程序以支持定义并显示矩形、圆角矩形、圆形、椭圆等4种形式的印章背景形状。   定义印章背景形状枚举类型&#xff0c;矩形、圆形、椭圆相关的尺寸…...

如何理解泛型的编译期检查

既然说类型变量会在编译的时候擦除掉&#xff0c;那为什么我们往 ArrayList 创建的对象中添加整数会报错呢&#xff1f;不是说泛型变量String会在编译的时候变为Object类型吗&#xff1f;为什么不能存别的类型呢&#xff1f;既然类型擦除了&#xff0c;如何保证我们只能使用泛型…...

计算机组成原理:海明校验

在上图中&#xff0c;对绿色的7比特数据进行海明校验&#xff0c;需要添加紫色的4比特校验位&#xff0c;总共是蓝色的11比特。紫色的校验位pi分布于蓝色的hi的1, 2, 4, 8, 16, 32, 64位&#xff0c;是2i-1位。绿色的数据位bi分布于剩下的位。 在下图中&#xff0c;b1位于h3&a…...

信息学奥赛初赛天天练-39-CSP-J2021基础题-哈夫曼树、哈夫曼编码、贪心算法、满二叉树、完全二叉树、前中后缀表达式转换

PDF文档公众号回复关键字:20240629 2022 CSP-J 选择题 单项选择题&#xff08;共15题&#xff0c;每题2分&#xff0c;共计30分&#xff1a;每题有且仅有一个正确选项&#xff09; 5.对于入栈顺序为a,b,c,d,e的序列&#xff0c;下列( )不合法的出栈序列 A. a&#xff0c;b&a…...

第11章 规划过程组(收集需求)

第11章 规划过程组&#xff08;一&#xff09;11.3收集需求&#xff0c;在第三版教材第377~378页&#xff1b; 文字图片音频方式 第一个知识点&#xff1a;主要输出 1、需求跟踪矩阵 内容 业务需要、机会、目的和目标 项目目标 项目范围和 WBS 可…...

探索WebKit的守护神:深入Web安全策略

探索WebKit的守护神&#xff1a;深入Web安全策略 在数字化时代&#xff0c;网络已成为我们生活的一部分&#xff0c;而网页浏览器作为我们探索网络世界的窗口&#xff0c;其安全性至关重要。WebKit作为众多流行浏览器的内核&#xff0c;例如Safari&#xff0c;其安全性策略是保…...

unity ScrollRect裁剪ParticleSystem粒子

搜了下大概有这几种方法 通过模板缓存通过shader裁剪区域&#xff1a;案例一&#xff0c;案例二&#xff0c;案例三&#xff0c;三个案例都是类似的方法&#xff0c;需要在c#传入数据到shader通过插件 某乎上的模板缓存方法link&#xff0c;&#xff08;没有登录看不到全文&a…...

凤仪亭 | 第7集 | 大丈夫生居天地之间,岂能郁郁久居人下 | 司徒一言,令我拨云见日,茅塞顿开 | 三国演义 | 逐鹿群雄

&#x1f64b;大家好&#xff01;我是毛毛张! &#x1f308;个人首页&#xff1a; 神马都会亿点点的毛毛张 &#x1f4cc;这篇博客分享的是《三国演义》文学剧本第Ⅰ部分《群雄逐鹿》的第7️⃣集《凤仪亭》的经典语句和文学剧本全集台词 文章目录 1.经典语句2.文学剧本台词 …...

React实战学习(一)_棋盘设计

需求&#xff1a; 左上侧&#xff1a;状态左下侧&#xff1a;棋盘&#xff0c;保证胜利就结束 和 下过来的不能在下右侧&#xff1a;“时光机”,保证可以回顾&#xff0c;索引 语法&#xff1a; 父子之间属性传递&#xff08;props&#xff09;子父组件传递&#xff08;写法上&…...

【LeetCode】每日一题:三数之和

解题思路 最开始是打算沿着二数之和的思路做&#xff0c;即固定了最大的&#xff0c;然后小的开始遍历&#xff0c;因为这种遍历方式只需要遍历一轮就能完成&#xff0c;所以复杂度应该是O&#xff08;n2&#xff09;&#xff0c;但是最后几个示例还是超时了&#xff0c;可能进…...

逆风而行:提升逆商,让困难成为你前进的动力

一、引言 生活&#xff0c;总是充满了未知与变数。有时&#xff0c;我们会遇到阳光明媚的日子&#xff0c;享受着宁静与和谐&#xff1b;但更多时候&#xff0c;我们却不得不面对那些突如其来的坏事件&#xff0c;如工作的挫折、人际关系的困扰、健康的挑战等。这些事件如同突…...

新能源汽车CAN总线故障定位与干扰排除的几个方法

CAN总线是目前最受欢迎的现场总线之一,在新能源车中有广泛应用。新能源车的CAN总线故障和隐患将影响驾驶体验甚至行车安全,如何进行CAN总线故障定位及干扰排除呢? 目前,国内机动车保有量已经突破三亿大关。由于大量的燃油车带来严峻的环境问题,因此全面禁售燃油车的日程在…...

【涵子来信】——社交宝典:克服你心中的内向,世界总有缺陷

内向&#xff0c;你是内向的吗&#xff1f;想必每个人不同&#xff0c;面对的情形也是不同的。 暑假是一个很好的机会&#xff0c;我是可以去多社交社交。但是&#xff0c;面对着CSDN上这么多技术人er&#xff0c;那么&#xff0c;我的宝典&#xff0c;对于大家&#xff0c;有…...

LabVIEW项目外协时选择公司与个人兼职的比较

​在选择LabVIEW项目外协合作伙伴时&#xff0c;外协公司和个人兼职各有优劣。个人兼职成本较低且灵活&#xff0c;但在可靠性、技术覆盖面、资源和风险管理上存在不足。而外协公司拥有专业团队、丰富资源、完善的项目管理和风险控制&#xff0c;尽管成本较高&#xff0c;但能提…...

汽车电子工程师入门系列——CAN 规范系列通读

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…...

泽众云真机-平台华为机型HarmonyOS NEXT系统已上线!

泽众云真机平台华为机型HarmonyOS NEXT系统已上线&#xff01; 之前文章《泽众云真机-平台即将升级支持华为机型HarmonyOS NEXT系统泽众云真机-平台即将升级支持华为机型HarmonyOS NEXT系统》&#xff0c;为什么要升级HarmonyOS NEXT系统&#xff1f;我们之前有说过&#xff0c…...

AI基础:从线性回归到梯度下降

一个简单的问题&#xff1a; 如果此时你正站在迷路缭绕的山坡上&#xff0c;能见度不高&#xff0c;但是你又想去往最低的山谷的位置&#xff0c;怎么走&#xff1f; 很简单&#xff0c;哪里陡那就往那里走呗——而这就是梯度下降算法的思想。 古话说&#xff1a;“先发制于人…...

AI产品经理面试

把优秀当习惯把优秀当习惯肯定不是口头说说&#xff0c;那有什么判断标准吗&#xff1f; 当我做完一件事儿的时候&#xff0c;我会看它有没有突破我的舒适圈、能不能惊艳到我自己。这就是我的判断标准。 在自我介绍和经历介绍时&#xff0c;面试者应该注重以下几个方面&#xf…...

二进制方式部署consul单机版

1.consul的下载 mkdir -p /root/consul/data && cd /root/consul wget https://releases.hashicorp.com/consul/1.18.0/consul_1.18.0_linux_amd64.zip unzip consul_1.18.0_linux_amd64.zip mv consul /usr/local/bin/ 2.配置文件 // 配置文件路径&#xff1a; /roo…...

SpringBoot整合Quartz实现动态定时任务

目录 1、Quartz简介1.1 Quartz的三大核心组件1.2 CronTrigger配置格式 2、SpringBoot整合Quartz框架2.1 创建项目2.2 实现定时任务 1、Quartz简介 Quartz是一个开源的任务调度服务&#xff0c;它可以独立使用&#xff0c;也可与其它的Java EE&#xff0c;Java SE应用整合使用。…...

qt 用宏控制静态接口的统一

1.概要 /** * 单件宏实验 * 创建一个可以生成单件的宏 * 起因&#xff1a;想让有些控件单件&#xff0c;但是c不支持静态的继承&#xff08;c#支持&#xff09; * 那么如果保证这些接口的统一呢&#xff0c;用宏 */ 2.代码 2.1 a.h #ifndef A_H #define A_H#include &…...

pdf怎么转换成jpg,本地转换还是在线转换?

PDF&#xff08;Portable Document Format&#xff09;和JPG&#xff08;Joint Photographic Experts Group&#xff09;这两种文件格式在我们的日常生活和工作中扮演着举足轻重的角色。PDF因其跨平台、保持原样性强的特点&#xff0c;被广泛应用于文件传输和存储&#xff1b;而…...

【物联网】802.15.4简介

目录 一、概述 二、802.15.4主要特点 2.1 工作频段和数据速率 2.2 支持简单器件 2.3 信标方式和超帧结构 2.4 数据传输和低功耗 三、低功耗 一、概述 802.15.4包括用于低速无线个人域网(LR-WPAN)的物理层和媒体接入控制层两个规范。它能支持消耗功率最少&#xff0c;一般…...

C++基础语法:复制构造函数,赋值构造函数及浅复制,深复制

前言 "打牢基础,万事不愁" .C的基础语法的学习 引入 前一篇帖子C基础语法:类构造函数之普通构造函数-CSDN博客讲了普通构造函数,还有 复制构造函数,赋值运算符以及延伸出来的浅复制和深复制问题,做个补充. 内容主要参考自<<C Prime Plus>> 6th Edition …...

架构是怎样练成的-楼宇监控系统案例

目录 概要 项目背景 原系统设计方案 改进后的设计方案 小结 概要 绝大多数人掌握的架构都是直接学习&#xff0c;慢慢地才能体会到一个架构的好处。架构是一种抽象&#xff0c;是为了复用目的而对代码做的抽象。通过一个项目的改造&#xff0c;理解架构是如何产生的&…...

valgrind使用浅谈

1、Valgrind 简介 Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件开发工具&#xff0c;它可在以下平台上运行&#xff1a; X86/Linux、AMD64/Linux、ARM/Linux、ARM64/Linux、PPC32/Linux、PPC64/Linux、PPC64LE/Linu x、S390X/Linux、MIPS32/Linux、MIPS64/Li…...

强化学习专题:强化学习知识梳理(一)

2024/6/23&#xff1a; 前段时间有幸完成了大学期间的第一篇论文。在面试之前复盘一下关于自己论文中DQN的一些相关点。 浅谈主要区别&#xff08;在线 or 离线&#xff09; 首先&#xff0c;一切的开始是强化学习中时序差分方程&#xff0c;这体现了强化学习方法的优化策略。在…...

深入JVM:详解JIT即时编译器

文章目录 深入JVM&#xff1a;详解JIT即时编译器一、序言二、基础概念1、何为JIT即时编译2、热点代码 三、HotSpot内置的即时编译器1、C1编译器2、C2编译器3、分层编译3.1 协作流程 四、常见JIT优化技术1、方法内联2、逃逸分析&#xff08;1&#xff09;同步锁消除&#xff08;…...

ORBSLAM3_ROS_Ubuntu18_04环境搭建安装

orbslam3安装 ORB-SLAM3配置及安装教程&#xff08;2023.3&#xff09;_orbslam3安装-CSDN博客 换源&#xff0c;换成国内的 搜索software 安装工具 sudo apt install git sudo apt update sudo apt install gcc g cmake安装 cmake安装新版本 ubuntu20.04安装cmake详细…...

【opencv - C++ - Ubuntu】putText 显示中文最快方法

话不多说&#xff0c;直接上代码 #include <iostream> #include <opencv2/opencv.hpp> #include <opencv2/freetype.hpp>using namespace std; using namespace cv;int main(void) {Mat image(1000, 1800, CV_8UC3, Scalar(200,162,33));Ptr<freetype::F…...

百度网盘下载速度慢的解决办法

目录 一、背景 二、解决办法 1、点击三个竖点&#xff0c;再点设置 2、点击传输&#xff0c;再点击去开启该功能 3、点击同意&#xff0c;开启优化速率 三、结果 四、备注 一、背景 当你不是百度网盘会员时&#xff0c;你在使用百度网盘下载时&#xff0c;是否下载速度太…...

Python api接口 异步

Python API接口异步编程简介 在现代的软件开发中&#xff0c;大多数应用都需要通过API接口与其他系统进行交互。Python是一种非常流行的编程语言&#xff0c;因此许多开发者选择使用Python来构建他们的API接口。在一些情况下&#xff0c;API接口需要进行异步编程&#xff0c;以…...

Java 和 Kotlin 单例模式写法对比

目录 1、饿汉模式 Java 写法&#xff1a; Kotlin 写法&#xff1a; Kotlin 这段代码反编译&简化后如下&#xff1a; 2、懒汉模式&#xff0c;静态同步方法 Java 写法&#xff1a; Kotlin 写法&#xff1a; Kotlin 这段代码反编译&简化后如下&#xff1a; 3、懒…...

解析connectionReset异常的原因与解决方案

解析connectionReset异常的原因与解决方案 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将深入探讨Java中connectionReset异常的原因及其解决方案。这…...

mindspore打卡第9天 transformer的encoder和decoder部分

mindspore打卡第9天 transformer的encoder和decoder部分 import mindspore from mindspore import nn from mindspore import ops from mindspore import Tensor from mindspore import dtype as mstypeclass ScaledDotProductAttention(nn.Cell):def __init__(self, dropout_…...

Python实现IPv4地址和16进制互相转换

Python实现IPv4地址和16进制互相转换 import socketdef ip_to_hex16(ipaddr):# 使用 socket 库中的方法将IP地址转换为网络字节序的二进制表示hex_bytes socket.inet_aton(ipaddr)# 将二进制数据转换为整数, 其中byteorderbig 表示使用大端字节序&#xff08;从高位到低位&…...

计算机视觉 | 基于图像处理和边缘检测算法的黄豆计数实验

目录 一、实验原理二、实验步骤1. 图像读取与预处理2. 边缘检测3. 轮廓检测4. 标记轮廓序号 三、实验结果四、完整代码 Hi&#xff0c;大家好&#xff0c;我是半亩花海。 本实验旨在利用 Python 和 OpenCV 库&#xff0c;通过图像处理和边缘检测算法实现黄豆图像的自动识别和计…...

深入分析 Android BroadcastReceiver (七)

文章目录 深入分析 Android BroadcastReceiver (七)1. 高级应用场景1.1 示例&#xff1a;动态权限请求1.2 示例&#xff1a;应用内通知更新 2. 安全性与性能优化2.1 示例&#xff1a;设置权限防止广播攻击2.2 示例&#xff1a;使用 LocalBroadcastManager2.3 示例&#xff1a;在…...

C++中的数据结构

一.STL标准库 结构:STL中有六大组件&#xff0c;分别是&#xff1a;容器&#xff0c;算法&#xff0c;迭代器&#xff0c;仿函数&#xff0c;配接器&#xff0c;配置器&#xff1b;以下分别介绍这六大组件中的最主要的三个。 1.容器 容器来配置存储空间&#xff0c;算法通过…...

武汉星起航:一站式服务,助力亚马逊卖家高效运营,实现收益飞跃

在跨境电商的浪潮中&#xff0c;武汉星起航电子商务有限公司以其独特的一站式跨境电商服务&#xff0c;为众多亚马逊卖家提供了强有力的支持&#xff0c;助力他们在不断发展的市场中脱颖而出&#xff0c;实现收益的大幅提升。 武汉星起航的一站式跨境电商服务&#xff0c;以其…...

从灵感到实践:Kimi辅助完成学术论文选题的文艺之旅

学境思源&#xff0c;一键生成论文初稿&#xff1a; AcademicIdeas - 学境思源AI论文写作 昨天我们为大家介绍了ChatGPT辅助完成实现设计&#xff08;AI与学术的交响&#xff1a;ChatGPT辅助下的实验设计新篇章&#xff09;。今天我们再来看看Kimi对于论文选题都能提供哪些帮助…...

华为od-C卷200分题目4 -电脑病毒感染

华为od-C卷200分题目4 -电脑病毒感染 一个局域网内有很多台电脑&#xff0c;分别标注为0 - N-1的数字。相连接的电脑距离不一样&#xff0c;所以感染时间不一样&#xff0c;感染时间用t表示。其中网络内一个电脑被病毒感染&#xff0c;其感染网络内所有的电脑需要最少需要多长…...

show-overflow-tooltip 解决elementui el-table标签自动换行的问题

elementui中 el-table中某一行的高度不想因为宽度不够而撑开换行展示的解决方法。可通过show-overflow-tooltip属性解决&#xff0c;如下 代码是这样的 <el-table-column width"80" prop"id" label"ID"></el-table-column> <el…...

数字社交的领航者:解析Facebook的引领作用

在当今数字化社会中&#xff0c;社交网络已经成为了人们日常生活不可或缺的一部分。而在众多社交平台中&#xff0c;Facebook凭借其巨大的用户基础和创新的技术应用&#xff0c;被公认为数字社交领域的领航者之一。本文将深入解析Facebook在数字社交中的引领作用&#xff0c;探…...

深度分析 Apache Flink 窗口机制

什么是 Flink 窗口&#xff1f; Apache Flink 是一个用于处理实时流数据的开源框架&#xff0c;其核心功能之一是窗口&#xff08;Window&#xff09;机制。窗口是 Flink 在处理流数据时用于划分数据流的逻辑概念&#xff0c;它将无限的流数据切割成有限的、可管理的部分&…...

【Linux】线程——线程的概念、线程的特点、线程的优点和缺点、线程和进程、线程函数的使用

文章目录 Linux线程1. 线程的概念1.1 什么是线程 2. 线程的特点2.1 线程的优点2.2 线程的缺点2.4 线程和进程 3. 线程函数的使用pthread_create() 创建线程pthread_self() 获取线程IDpthread_exit() 线程终止pthread_cancel() 线程取消pthread_join() 线程等待pthread_detach()…...

docker配置redis主从复制

下载redis,复制redis.conf 主节点(6379) 修改redis.conf # bind 127.0.0.1 # 注释掉这里 protected-mode no # 改为no port 6379从节点(6380) 修改redis.conf bind 127.0.0.1 protected-mode no # 改为no port 6380 replicaof 172.17.0.2 6379 # 这里的ip为主节点容器的i…...

爬虫-网页基础

HTML 基本语法 HTML&#xff1a;Hyper Text Markup Language, 超文本标记语言&#xff0c;是计算机语言的一种&#xff0c;由元素构成。 p元素 <p>Web 真好玩&#xff01;</p> 由三大部分组成 开始标签&#xff1a;一对尖括号中间包裹这元素名称元素内容&#x…...

大数据面试题之HBase(3)

HBase的预分区 HBase的热点问题 HBase的memstore冲刷条件 HBase的MVCC HBase的大合并与小合并&#xff0c;大合并是如何做的?为什么要大合并 既然HBase底层数据是存储在HDFS上&#xff0c;为什么不直接使用HDFS&#xff0c;而还要用HBase HBase和Phoenix的区别 HBase支…...

React useImperativeHandle Hook

useImperativeHandle Hook 是一个比较比较简单的 hook&#xff0c;为 ref 节点添加一些处理方法&#xff0c;下面是来自官网例子&#xff0c;为 ref 添加了两个方法。 import { forwardRef, useRef, useImperativeHandle } from react;const MyInput forwardRef(function MyI…...

友思特应用 | 多接口的智驾无忧:GigE相机在自动驾驶数据采集系统的稳定应用

导读 GigE接口相机为自动驾驶数据采集提供了高性价比的选择。在此基础上&#xff0c;友思特搭建了多GigE接口支持PTP的采集设备系统级方案 BRICK2&#xff0c;为多传感器数据记录测试提供了完整的解决方案。 GigE接口相机与智能驾驶数据采集 智能驾驶技术的发展已经成为当今科…...

未来三年雷军和他的小米汽车首先不得不为生存而战

小米SU7正式上市,可谓红透了汽车界。雷军及小米汽车多个话题登上热搜,而大定的数据也映衬出小米SU7的热度。然而,在一片喧嚣声中,我倒觉得,未来三年雷军和他的小米汽车首先不得不为生存而战。未来三年小米汽车大概率将是亏损运营。从这次小米SU7的定价就可以看出端倪。小米…...

新火种AI|寻求合作伙伴,展开豪赌,推出神秘AI项目...苹果能否突破AI困境?

作者&#xff1a;小岩 编辑&#xff1a;彩云 2024年&#xff0c;伴随着AI技术的多次爆火&#xff0c;不仅各大科技巨头纷纷进入AI赛道展开角力&#xff0c;诸多智能手机厂商也纷纷加紧布局相关技术&#xff0c;推出众多AI手机。作为手机领域的龙头老大&#xff0c;苹果自然是…...

Unix环境高级编程--8-进程控制---8.1-8.2进程标识-8.3fork函数-8.4 vfork函数

1、进程控制几个过程 创建进程--》执行进程---》终止进程 2、进程标识 &#xff08;1&#xff09;专用进程&#xff1a;ID为0的进程是调度进程&#xff0c;常常被称为交换进程&#xff0c;也称为系统进程&#xff1b; ID为1通常是init进程&#xff0c;在自举结束时由内核调用…...

Flutter 中的 Viewport 小部件:全面指南

Flutter 中的 Viewport 小部件&#xff1a;全面指南 Flutter 是一个现代的移动和 web 应用开发框架&#xff0c;它允许开发者以一种非常直观和高效的方式构建用户界面。在 Flutter 中&#xff0c;Viewport 是一个非常重要的小部件&#xff0c;它提供了一个滚动视口&#xff0c…...

shell脚本:将一维数组以二维数组显示

shell脚本:将一维数组改成二维数组显示 1.编辑脚本文件 vi output_array.sh2.编写脚本 #!/bin/bash# 假设一维数组one_array已经包含9个元素 one_array=(1 2 3 4 5 6 7 8 9) # 获取数组长度 length=...

vue3(一):Vue3简介、创建vue3工程、Vue3中的响应式

目录 一.Vue3简介 1.性能提升 2.源码升级 3.拥抱ts 4.新特性 &#xff08;1&#xff09;Composition API&#xff08;组合API&#xff09;&#xff1a; &#xff08;2&#xff09;新的内置组件&#xff1a; &#xff08;3&#xff09;其他改变&#xff1a; 二.创建vue…...